ruby has gems, macOS has brew, go has go mod
Go Mod is the next iteration of dep
that is built into go and allows developers to work outside of GOPATH.
Let's create an example project in an empty folder outside of GOPATH:
main.tf
package main
import (
"github.com/user/project/pkg/hello" // Don't change this for now
)
func main() {
hello.Greet()
}
pkg/hello/greeter.go
package hello
import "fmt"
func Greet() {
fmt.Println("greetings")
}
Remember: the go compiler previously only looks in GOPATH and GOROOT to try to match import paths.
» go run main.go
main.go:4:4: cannot find package "github.com/user/project/pkg/hello" in any of:
/usr/local/Cellar/go/1.13.4/libexec/src/github.com/user/project/pkg/hello (from $GOROOT)
/Users/username/go/src/github.com/user/project/pkg/hello (from $GOPATH)
» go mod init github.com/user/project # Run this as is for now.
go: creating new go.mod: module github.com/user/project
» go run main.go
greetings
What happened here? Go now knows to treat this directory as "github.com/user/project", and can resolve the import path.
go mod init
created a go.mod
file:
module github.com/user/project
go 1.13
Let's expand go mod to use remote packages.
main.go
package main
import (
"github.com/user/project/pkg/hello"
"github.com/sirupsen/logrus"
)
func main() {
hello.Greet()
logrus.Info("hello")
}
Let's run go run main.go
to verify that everything works, then explore go.mod:
module github.com/user/project
go 1.13
require github.com/sirupsen/logrus v1.4.2 // indirect
We can see that mod
is now managing the versioned logrus dependency in go.mod.
Similar to GOPATH/src, go mod stores its dependencies in GOPATH/pkg/mod instead of GOPATH/src.
We can see the // indirect
comment because go run
wrote to the file. If we remove the last line entirely and run go mod tidy
we will see it without the comment.
Usually, the // indirect
comment tells us that a package we depend on is depending on yet another package.
That's it! You can now forget everything you knew about GOPATH and GOROOT.
go help mod
go help mod tidy