Based on this Stack Overflow answer
Before the introduction of Go modules, the file structure of local Go projects were like
// an executable
$GOPATH/github.com/you/project1
-> $GOPATH/github.com/you/project1/package_main
-> $GOPATH/github.com/you/project1/package1
-> $GOPATH/github.com/user_a/project1/package2 // imports project3
-> $GOPATH/github.com/user_a/project1/package3// an executable
$GOPATH/github.com/user_b/project2
-> $GOPATH/github.com/user_b/project2/main_package
-> $GOPATH/github.com/user_b/project2/package_a
-> $GOPATH/github.com/user_b/project2/package_b// a library
$GOPATH/github.com/user_c/project3
-> $GOPATH/github.com/user_b/project2/package_a
-> $GOPATH/github.com/user_b/project2/package_b
While it’s simple, it’s also cumbersome and error-prone.
After the introduction of Go modules, project management gets more convenient but also more complicated. The old way still works, of course, but is no longer recommended, and you can now place your project anywhere you like, like $HOME/projects/my_go_project
and initialize your project as go mod init github.com/you/my_go_project
. However, it’s where things can get complicated, and as you will see shortly, github.com/you/my_go_project
is now more like a name and has nothing to do with the actual path to where the code lives. Let’s say you currently have three projects as listed below:
$GOPATH/github.com/user_b/project2
-> $GOPATH/github.com/user_b/project2/main_package
-> $GOPATH/github.com/user_b/project2/package_a
-> $GOPATH/github.com/user_b/project2/package_b// a library
$GOPATH/github.com/user_c/project3
-> $GOPATH/github.com/user_b/project2/package_a
-> $GOPATH/github.com/user_b/project2/package_b...$HOME/somewhere_you_like/project
-> $HOME/somewhere_you_like/project/main_package
-> $HOME/somewhere_you_like/project/package_a
-> $HOME/somewhere_you_like/project/package_b
How do you import package_a
now? Definitely not like import $HOME/somewhere_you_like/project/package_a
, right? It will break if someone else downloads and wants to compile your code. Actually, according to the How to Write Go Code tutorial, you should still write imports like import github.com/you/project/package_n
and go’s build tools will handle the rest for you, and that’s also why I said github.com/you/project
is more of a name than its actual path.
To sum up, if you run go get
, the downloaded files will go to $GOPATH
; if you run go build
from a non-main package, you will get nothing (the result will be cached somewhere though), and if you run go build
from the main package, you will get a binary alongside existing files; if you run go install
from a non-main package, you will get a binary file installed under the $GOPATH/pkg
directory and if you run go install
from the main package, you will get an executable file under $GOPATH/bin
.
Read Go’s offcial blog for more information on this topic.