Go build project with cmd and pkg layout - build error - go

I'm trying to build a Go project using the layout as described in Go Project Layout
I'm using go 1.9.2 on Ubuntu. My project layout is as follows
$GOPATH/src/github.com/ayubmalik/cleanprops
/cmd
/cleanprops
/main.go
/internal
/pkg
/readprops.go
The file cmd/cleanprops/main.go is referring to the cleanprops package i.e.
package main
import (
"fmt"
"github.com/ayubmalik/cleanprops"
)
func main() {
body := cleanprops.ReadProps("/tmp/hello.props")
fmt.Println("%s", body)
}
The contents of internal/pkg/readprops.go are:
package cleanprops
import (
"fmt"
"io/ioutil"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func ReadProps(file string) string {
body, err := ioutil.ReadFile(file)
check(err)
fmt.Println(string(body))
return body
}
However when I build cmd/cleanprops/main.go, from inside directory $GOPATH/src/github.com/ayubmalik/cleanprops, using command:
go build cmd/cleanprops/main.go
I get the following error:
cmd/cleanprops/main.go:5:2: no Go files in /home/xyz/go/src/github.com/ayubmalik/cleanprops
What am I missing?

The document suggests this structure:
$GOPATH/src/github.com/ayubmalik/cleanprops
/cmd
/cleanprops
/main.go
/internal
/pkg
/cleanprops
/readprops.go
Import the package like this. The import path matches the directory structure below $GOPATH/src.
package main
import (
"fmt"
"github.com/ayubmalik/cleanprops/internal/pkg/cleanprops"
)
func main() {
body := cleanprops.ReadProps("/tmp/hello.props")
fmt.Println("%s", body)
}

Related

Relative import in Go for protobuf , cannot find module path

I'm trying to write a service in go with gRPC, and when i import the protobuff file , getting an error. i tried removing all the modules in my go path and reinitialising the go modules
build _/Users/tibinlukose/cart-service/pb: cannot find module for path _/Users/tibinlukose/cart-service/pb
Code
package main
import (
pbcart "../pb/"
"log"
"fmt"
"google.golang.org/grpc"
"net"
)
var (
port = 1000;
)
type CartServiceServer struct {
}
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
fmt.Println("Server Starting ..")
lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", 10000))
if err != nil {
log.Fatal("unable to listen on the port")
}
serverOptions := []grpc.ServerOption{}
grpcServer := grpc.NewServer(serverOptions...)
srv := &CartServiceServer{}
pbcart.RegisterCartServiceServer(grpcServer, srv)
}
env
GOCACHE="/Users/tibinlukose/Library/Caches/go-build"
GOENV="/Users/tibinlukose/Library/Application Support/go/env"
GOPATH="/Users/tibinlukose/go"
GOROOT="/usr/local/Cellar/go/1.13.4/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.13.4/libexec/pkg/tool/darwin_amd64"
GOMOD="/Users/tibinlukose/cart-service/server/go.mod"
repo https://github.com/zycon/cart-service
Move your go.mod to the root and update import to github.com/zycon/cart-service/pb?
There is no relative import in Go. You can see this answer for an extended explanation: Relative imports in Go
There is a proposal: https://github.com/golang/go/issues/20883

Is there a way to extract package path from reflect.Func? [duplicate]

I'm having difficulty when trying to get path of imported package. When I print result of os.Getwd() inside imported package, it's showing same path like on main package.
This what I did.
Project structure
lib/lib.go
package lib
import "os"
import "fmt"
func init() {
dir, _ := os.Getwd()
fmt.Println("lib.init() :", dir)
}
func GetPath() {
dir, _ := os.Getwd()
fmt.Println("lib.GetPath() :", dir)
}
main.go
package main
import "os"
import "fmt"
import "test-import/lib"
func main() {
dir, _ := os.Getwd()
fmt.Println("main :", dir)
lib.GetPath()
}
Result
lib.init() : /Users/novalagung/Documents/go/src/test-import
main : /Users/novalagung/Documents/go/src/test-import
lib.GetPath() : /Users/novalagung/Documents/go/src/test-import
The result of os.Getwd() from lib/lib.go is still same path like on main. What I want is the real path of the package which is /Users/novalagung/Documents/go/src/test-import/lib/
What should I do? Is it possible?
If you can get a reference to something in the package, you can use reflect to get the import path.
Here's an example on Play:
package main
import (
"bytes"
"fmt"
"reflect"
)
func main() {
var b bytes.Buffer
fmt.Println(reflect.TypeOf(b).PkgPath())
}
PkgPath() only can retrieve the package path for non-pointer
// If the type was predeclared (string, error) or not defined (*T, struct{},
// []int, or A where A is an alias for a non-defined type), the package path
// will be the empty string.
func packageName(v interface{}) string {
if v == nil {
return ""
}
val := reflect.ValueOf(v)
if val.Kind() == reflect.Ptr {
return val.Elem().Type().PkgPath()
}
return val.Type().PkgPath()
}

How to import imported package's vendor package

I am using etcd's wal package (https://godoc.org/github.com/coreos/etcd/wal) to do write-ahead logging. wal has go.uber.org/zap in its vendor packages. In wal's create function func Create(lg *zap.Logger, dirpath string, metadata []byte) (*WAL, error), I need to pass in zap.Logger.
I have tried to import go.uber.org/zap but go compiler complains "type mismatch" when I pass in zap.Logger.
package main
import (
"github.com/coreos/etcd/wal"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
metadata := []byte{}
w, err := wal.Create(zap.NewExample(), "/tmp/hello", metadata)
// err := w.Save(s, ents)
}
How should I use zap.Logger in my project?
It seems like the package github.com/coreos/etcd/wal is not meant to be used outside of the etcd project. If you really need to use it, please, follow the steps below.
Place the following code in the $GOPATH/src/yourpackage/main.go file.
package main
import (
"fmt"
"go.etcd.io/etcd/wal"
"go.uber.org/zap"
)
func main() {
metadata := []byte{}
w, err := wal.Create(zap.NewExample(), "/tmp/hello", metadata)
fmt.Println(w, err)
}
mkdir $GOPATH/src/yourpackage/vendor
cp -r $GOPATH/src/go.etcd.io $GOPATH/src/yourpackage/vendor/
mv $GOPATH/src/yourpackage/vendor/go.etcd.io/etcd/vendor/go.uber.org $GOPATH/src/yourpackage/vendor/
go build yourpackage

How do I fix this import?

main_test.go
package main_test
import (
"log"
"os"
"testing"
"."
)
func TestMain(m *testing.M) {
a = main.App{}
a.Init(
os.Getenv("TEST_DB_USERNAME"),
os.Getenv("TEST_DB_PASSWORD"),
os.Getenv("TEST_DB_NAME"))
ensureTableExists()
code := m.Run()
clearTable()
os.Exit(code)
}
app.go
package main
import (
"database/sql"
"fmt"
"log"
"github.com/gorilla/mux"
_ "github.com/lib/pq"
)
type App struct {
Router *mux.Router
DB *sql.DB
}
func (a *App) Init(user, password, dbname string) {
connection := fmt.Sprintf("user=%s password=%s dbname=%s", user, password, dbname)
var err error
a.DB, err = sql.Open("postgres", connection)
if err != nil {
log.Fatal(err)
}
a.Router = mux.NewRouter()
}
func (a *App) Run(addr string) { }
main.go
package main
import "os"
func main() {
a := App{}
a.Init(
os.Getenv("APP_DB_USERNAME"),
os.Getenv("APP_DB_PASSWORD"),
os.Getenv("APP_DB_NAME"))
a.Run(":8080")
}
Hey everyone, I am brand new to Golang and working with some tutorials. In the tutorial, they are using the import statement "." which is throwing an error for me. The exact error is "Non-canonical import-path." I tried using a relative path and full path to access the main file in my project but when I use anything other than "." the var a.main.App throws an error saying that main is an unresolved type. My $GOPATH is set to c:/users/me/go/src my project lives in the src folder. I am not entirely sure what is wrong my code at the moment. If it is something glaringly obvious I apologize.
Here is what I am trying to import. This lives in a file called app.go which is called through main.go
type App struct {
Router *mux.Router
DB *sql.DB
}
You don't need to import main for using struct App. You simply change the package of main_test to main then you can able to use that struct, like below i simply passed the main_test file.
package main
import (
"os"
"testing"
)
func TestMain(m *testing.M) {
a := App{}
a.Init(
os.Getenv("TEST_DB_USERNAME"),
os.Getenv("TEST_DB_PASSWORD"),
os.Getenv("TEST_DB_NAME"))
ensureTableExists()
code := m.Run()
clearTable()
os.Exit(code)
}
Here what i get from execute the test:
Success: Tests passed.

Running multi-file go program

So I'm pretty new to go and I'm trying to follow this tutorial -
http://thenewstack.io/make-a-restful-json-api-go/
Right now, this is my file structure -
EdData/
dataEntry/
populateDb.go
main.go
handlers.go
routes.go
When I run go run main.go, I get this error ./main.go:11: undefined: NewRouter
This is what my main.go looks like -
package main
import (
"net/http"
"log"
)
func main() {
router := NewRouter()
log.Fatal(http.ListenAndServe(":8080", router))
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
This is what my routes.go looks like
package main
import (
"net/http"
"github.com/gorilla/mux"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes[]Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
return router
}
var routes = Routes{
Route {
"Index",
"GET",
"/",
Index,
},
}
and this is what my handlers.go looks like
package main
import (
"fmt"
"net/http"
)
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "WELCOME!")
}
When I try and build routes.go, I get that Index is undefined, and when I try and build handlers.go, I get
# command-line-arguments
runtime.main: undefined: main.main
How do I get this to run? Also, where do I execute the go run command? Do I need to manually build all the dependent files?
From the go run help:
usage: run [build flags] [-exec xprog] gofiles... [arguments...]
Run compiles and runs the main package comprising the named Go source files.
A Go source file is defined to be a file ending in a literal ".go" suffix.
Only the files passed to go run will be included in the compilation (excluding imported packages). Therefore, you should specify all of your Go source files when using go run:
go run *.go
# or
go run main.go handlers.go routes.go

Resources