Multimodule Go Importing From Wrong Path - go

I have the following structure:
gateway-service
config
config.go
go.mod
go.sum
service.go
logger
logger.go
go.mod
go.sum
In config.go I import the following:
import (
"errors"
"os"
"strings"
"github.com/spf13/viper"
)
Now, the top level packages are fine and import correctly. However, the viper package does not. The error message is:
could not import github.com/spf13/viper (cannot find package "github.com/spf13/viper" in any of
/Users/me/.go/src/github.com/spf13/viper (from $GOROOT)
/Users/me/go/src/github.com/spf13/viper (from $GOPATH))compiler
The same issue happens in the logger.go file:
package logger
import (
"context"
"go.uber.org/zap"
)
The error is:
could not import go.uber.org/zap (cannot find package "go.uber.org/zap" in any of
/Users/me/.go/src/go.uber.org/zap (from $GOROOT)
/Users/me/go/src/go.uber.org/zap (from $GOPATH))compiler
I've tried installing with:
go get github.com/spf13/viper
go get go.uber.org/zap
go mod tidy
gateway-service/go.mod
module github.com/puul/gateway-service
go 1.15
require github.com/spf13/viper v1.3.2
logger/go.mod
module github.com/puul/logger
go 1.15
require (
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.16.0
)
Go env:
▶ echo $GOPATH
/Users/me/go
▶ echo $GOROOT
/Users/me/.go
On a related note, I'd love to know if there was a simpler way to achieve a structure like this:
pkg
logger
logger.go
services
gateway
Edit
My guess is that I have a conflict somehow between modules and GOPATH. Frankly, it's not clear from documentation how the two interact. Autoimports appear to be broken in VSCode as a result. It should be pulling from the path given in the import but it is not. What determines that import path is the core issue.

The (from $GOPATH) strings in the error message indicates that the go command invocation that produced that error was running in GOPATH mode, not module mode — which probably means that your current working directory was not within either of the two modules.
In general we recommend using a single module for your code unless you have a strong need to release different sets of packages at different times.
If you are using VSCode to edit code across multiple modules, you may need to configure your workspace to tell it which is the main module; see the build.experimentalWorkspaceModule setting.
You may also need (or want) to plumb the logger module into the gateway-service module using a replace directive.

Related

Import Github package in go

I'm trying out AWS Lambda in go and have the following imports.
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/aws/aws-lambda-go/lambda"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
)
Among these I'm unable to resolve the import for package aws-sdk-go. It always suggests to create such directory in GOPATH:/src.
Here's what I have tried so far:
Checked GOPATH is right.
I also did go mod vendor which resulted in vendor directory in my project and it has aws-sdk-go under it
Did go get github.com/aws/aws-sdk-go and this downloaded this sdk to my GOPATH and it looks like this pkg/mod/github.com/aws/aws-sdk-go#v1.44.138/aws
When I try to use pkg/mod/github.com/aws/aws-sdk-go#v1.44.138/aws in my import, it complains that there cannot be # in import.
I don't get why it doesn't refer to the package in vendor directory just like the other import github.com/aws/aws-lambda-go/lambda
Any ideas what's going on?
As indicated in the comments above, the issue was not with go code itself but the IDE.
I use IntelliJ and had GOPATH set and Module integration disabled.
To resolve the issue I removed GOPATH and enabled Module integration.
To understand Modules this blog helped me: https://go.dev/blog/using-go-modules

no matching versions for query "latest" with a local package

go version go1.15.2 darwin/amd64
within my folder I have two files: main.go and user.go along with other files such as go.mod, go.sum etc.
when trying to import the package from user.go I get the error in my imports:
no matching versions for query "latest"
user.go
package user
import (
"os"
"os/user"
"path/filepath"
)
main.go
import (
"fmt"
"bufio"
"github.com/ctfrancia/go-dot/user" // <--- error here
// ...
)
I tried following some suggestions such as go clean -modcache as suggested in a git hub issue
I'm using gomods so I don't want to disable it. Thanks
so my mistake was that the folder in the directory is the package name... well best practice:
so: goApplication/pkg/hello all the subsequent .go files should have package hello at the top
Your files user.go and main.go are in same directory, in golang if you want to work with custom packages you have to create directories with the same name as your package name in your case your directory structure will be something like:
goApplication/rootDir
- main.go
- user
-- user.go
Note: You can also use pkg/user directory but it is not mandatory for small projects and community has positive as well as negative remarks for this layout structure.

Can't import a package from a different file in GO

I am using go1.13.4 and below is my project structure:
src/types/type.go
src/utils/util.go
go.mod
In go.mod:
module example.com/graphql
go 1.13
require github.com/graph-gophers/graphql-go v0.0.0-20191031232829-adde0d0f76a3
In src/types/type.go:
package types
type USER struct {
...
}
In src/utils/util.go,
package utils
import (
"example.com/graphql/types"
"fmt"
"io/ioutil"
"os"
)
I got tan error when build the project:
$ go build ./...
src/utils/utils.go:4:2: cannot find module providing package example.com/graphql/types
I wonder why it can't find the package example.com/graphql/types? I am reading https://blog.golang.org/using-go-modules and I already set the module name in go.mod file at the root of my project.
With your current layout, import path of types is example.com/graphql/src/types.
go.mod should be inside src if you have that structure. Or better would be to get rid of src. go.mod must be next to the types and utils folders.

Go 1.12 modules: local import in non-local import

I'm currently using Go 1.12 modules and really tired about importing.
I'm making the rest-api using gin(web microservices) and gorm(golang orm). Everything still ok while working in golang modules. But getting trouble with local packages importing
The directory tree:
The go.mod:
module github.com/Aragami1408/go-gorm
go 1.12
require (
github.com/gin-gonic/gin v1.4.0
github.com/jinzhu/gorm v1.9.9
github.com/lib/pq v1.1.1
github.com/satori/go.uuid v1.2.0
)
The db.go:
package db
//code below...
The tasks.go:
package task
import (
"../db"
)
But when I run and still get this error:
local import "../db" in non-local package
I've searched a lot on google and nothing helps
From "Do modules work with relative imports like import "./subdir"?"
In modules, there finally is a name for the subdirectory.
If the parent directory says "module m" then the subdirectory is imported as "m/subdir", no longer "./subdir".
In your case:
import "github.com/Aragami1408/go-gorm/db"
# or maybe
import "go-gorm/db"
This assumes, as commented below by Silvio Lucas, that you have set GO111MODULE=on.
If you are using go modules you can replace your package by a local one using:
go mod edit -replace github.com/username/project=/localpath
then just call
go get github.com/username/project
and everything should work fine.
When migrating to go as "package manager", you may create the file go mod using the command :
go mod init myhost/myrepo/mymodule
Then the file will be created go.mod will be created :
module myhost/myrepo/mymodule
go 1.15
Now you can leverage this file to list your dependencies to other modules :
# i.e: your module mymodule depennds on github.com/gorilla/mux
got get github.com/gorilla/mux
You run it ? then check again the content of go.mod
module myhost/myrepo/mymodule
go 1.15
require (
github.com/gorilla/mux v1.7.4
)
You are happy because you leverage the package manager features and you are managing dependencies like a Boss.
However,....
However, you forget that you need to maintain all go files which imports directories with relative paths.
example :
if you have main.go
package main
import (
"fmt"
"./router" // !! RELATIVE PATH
)
You must migrate also by replacing the relative path by [module-name]/relative-path. in this case, it must become :
package main
import (
"fmt"
"myhost/myrepo/mymodule/router" // !! 💼 No more RELATIVE PATH
)

How to import local packages in go?

I am new to go and working on an example code that I want to localize.
In the original main.go import statement it was:
import (
"log"
"net/http"
"github.com/foo/bar/myapp/common"
"github.com/foo/bar/myapp/routers"
)
Now I have common and routers package in /home/me/go/src/myapp
So I converted the import statement to:
import (
"log"
"net/http"
"./common"
"./routers"
)
But when I run go install myapp I get these errors:
can't load package: /home/me/go/src/myapp/main.go:7:3: local import "./common" in non-local package
Also, when I use common and routers instead of ./common and ./routers in the import statement, I get:
myapp/main.go:7:3: cannot find package "common" in any of:
/usr/local/go/src/common (from $GOROOT)
/home/me/go/src/common (from $GOPATH)
myapp/main.go:8:2: cannot find package "routers" in any of:
/usr/local/go/src/routers (from $GOROOT)
/home/me/go/src/routers (from $GOPATH)
How can I fix this?
Well, I figured out the problem.
Basically Go starting path for import is $HOME/go/src
So I just needed to add myapp in front of the package names, that is, the import should be:
import (
"log"
"net/http"
"myapp/common"
"myapp/routers"
)
If you are using Go 1.5 above, you can try to use vendoring feature.
It allows you to put your local package under vendor folder and import it with shorter path.
In your case, you can put your common and routers folder inside vendor folder
so it would be like
myapp/
--vendor/
----common/
----routers/
------middleware/
--main.go
and import it like this
import (
"common"
"routers"
"routers/middleware"
)
This will work because Go will try to lookup your package starting at your project’s vendor directory (if it has at least one .go file) instead of $GOPATH/src.
FYI: You can do more with vendor, because this feature allows you to put "all your dependency’s code" for a package inside your own project's directory so it will be able to always get the same dependencies versions for all builds. It's like npm or pip in python, but you need to manually copy your dependencies to you project, or if you want to make it easy, try to look govendor by Daniel Theophanes
For more learning about this feature, try to look up here
Understanding and Using Vendor Folder by Daniel Theophanes
Understanding Go Dependency Management by Lucas Fernandes da Costa
I hope you or someone else find it helpfully
You should have created your package with go mod init e.g. go mod init github.com/my-org/my-package
Now in my-package you have a sub module called utils for example.
main.go
utils
|- randstr.go
And your randstr.go looks like this:
package utils
func RandStr(n int) string {
// TODO: Generate random string....
return "I am a random string"
}
And then anywhere in your project you would use exported functions from the utils package like this, for example in main.go:
package main
import (
"fmt"
// "github.com/my-org/my-package" is the module name at the
// top of your `go.mod`
"github.com/my-org/my-package/utils"
)
func main() {
fmt.Printf("Random string: %s\n", utils.RandStr(20))
}
Import paths are relative to your $GOPATH and $GOROOT environment variables. For example, with the following $GOPATH:
GOPATH=/home/me/go
Packages located in /home/me/go/src/lib/common and /home/me/go/src/lib/routers are imported respectively as:
import (
"lib/common"
"lib/routers"
)
an example:
in ./greetings, do go mod init example.com/greetings
from another module, do go mod edit -replace=example.com/greetings=../greetings
go get example.com/greetings
from the go tutorial
Local package is a annoying problem in go.
For some projects in our company we decide not use sub packages at all.
$ glide install
$ go get
$ go install
All work.
For some projects we use sub packages, and import local packages with full path:
import "xxxx.gitlab.xx/xxgroup/xxproject/xxsubpackage
But if we fork this project, then the subpackages still refer the original one.
Follow instructions here https://go.dev/doc/tutorial/call-module-code
Mainly you need the replace call in your go.mod file.
module example.com/hello
go 1.16
replace example.com/greetings => ../greetings
As in the question, the folder structure is:
/home/me/go/src/myapp
└─ common
└─ routers
So go to myapp dir
cd /home/me/go/src/myapp
Do
go mod init myapp
This will create a go.mod file which lets Go know the name of the module myapp so that when it’s looking at import paths in any package, it knows not to look elsewhere for myapp
Then you can do the following in the code:
import (
"log"
"net/http"
"myapp/common"
"myapp/routers"
)
Now package common and routers gets imported.
Another approach, available since go1.18, is to use a go.work file.
First, the local common package has to be a module, so provide a go.mod file inside the common folder:
module common
go 1.18
You can now create a go.work file in the root of your directory manually or call go work init, then go work use . and finally go work use ./common. It will look like this:
go 1.18
use (
.
./common
)
Finally you can import the package in your code by name
package main
import "common"
Just remember to not commit your go.work files :)
The key is how you name your module in the following command
go mod init <TheNameGiven>
Then refer the modules in the inner folder with,
TheNameGiven/folder
I have found the best solution here... Read More
Try to change the package name with the go mod init command.
So, I have go 1.17, and I have the same import problem. My project directory is $GOPATH/src/myswagger/app-swagger-test. I ran this command into app-swagger-test dir:
go mod init app-swagger-test
go mod tidy
In my new go.mod file the package name is app-swagger-test. For example, this import was wrong:
import (
...
"myswagger/app-swagger-test/internal/generated/restapi"
"myswagger/app-swagger-test/internal/generated/restapi/operations"
)
So I removed go.mod and go.sum. And I ran next commands into app-swagger-test dir:
go mod init myswagger/app-swagger-test
go mod tidy
After that all imports in the project were imported successfully. In the new go.mod file the first line is:
module myswagger/app-swagger-test
Maybe this information is common, but I did not find it. Thanks!

Resources