Take a look at this shell session, where I build a simple hello world program in Go.
$ cd ~/lab/hello/
$ ls
hello.go
$ cat hello.go
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
$ go build
$ ./hello
hello, world
$ go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH=""
GORACE=""
GOROOT="/usr/lib/go"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.7 (jessie)
Release: 8.7
Codename: jessie
Here is what I don't understand. The tutorial at https://golang.org/doc/install#testing says that I should place my hello.go
file at ~/go/src/hello. But I am not following this. How is my program compiling then? If my program is compiling fine in this manner, why does the documentation say that I should keep my source code at ~/go/src or $GOPATH/src when it does not seem to matter?
Is there a scenario where it is really necessary to place the source code at $GOPATH/src?
$GOPATH contains source code and binaries. With the latest release of Go 1.11, Go Modules are introduced which let you create your project outside the $GOPATH and improves package management a lot.
src contains Go source files, and. bin contains executable commands.
You don't need to set the GOPATH, it is set by default. The GOPATH directory is also named a workspace. Instead of randomly placing your code somewhere, you can use the gopath src directory. This is a mistake many beginners make, placing their code anywhere on the computer.
Source code for a program written in Go, a programming language originally developed by Google; contains code written in plain text format that must be compiled before being run as a program.
The standard Go tools look in the $GOPATH
subdirectories src
, pkg
, and bin
. For example,
currency.go
:
package main
import (
"fmt"
"time"
"golang.org/x/text/currency"
)
func main() {
t1799, _ := time.Parse("2006-01-02", "1799-01-01")
for it := currency.Query(currency.Date(t1799)); it.Next(); {
from := ""
if t, ok := it.From(); ok {
from = t.Format("2006-01-01")
}
fmt.Printf("%v is used in %v since: %v\n", it.Unit(), it.Region(), from)
}
}
Output:
$ go build currency.go
currency.go:7:2: cannot find package "golang.org/x/text/currency" in any of:
/home/peter/go/src/golang.org/x/text/currency (from $GOROOT)
/home/peter/gopath/src/golang.org/x/text/currency (from $GOPATH)
$
If we put the missing package in $GOPATH/src
, the standard Go tools will find it.
$ go get golang.org/x/text/currency
$ go build currency.go
$ ./currency
GBP is used in GB since: 1694-07-07
GIP is used in GI since: 1713-01-01
USD is used in US since: 1792-01-01
$
You really need to put your code in a GOPATH
once you write more than a package main
. When you import "github.com/me/myapp/mylib"
, Go will look under your GOPATH
for that. Tools like go test
also work in terms of packages under GOPATH
, not .go
files.
It also becomes the more practical thing to do as soon as your code is in more than one file. It's like the difference between compiling your C program by directly invoking cc
/gcc
/etc. and using a tool like make
.
If you're starting out and wondering why people want to break up projects into multiple packages in the first place, reasons include:
import
them separately.gzip.Reader
and io.Reader
. If you choose your names right, packagename.ThingName
can make code read naturally./foo/internal/
only get used by packages under /foo/
. Constraints like these can help keep a big project from ending up like tangled spaghetti.There are other benefits but those should help show why it's worth getting in the habit. It's fine to just charge forward writing things in a big package for a little bit and start breaking up files moving some types, functions, etc. out into other packages as needed; the 'natural' boundaries will start to make more sense over time.
As JimB says in his comment, the Go documentation makes this clear; basically, the GOPATH is workspace which allows you to keep all your project files and imports and artifacts in one location.
For a simple project it's not strictly necessary, but when you begin importing dependencies and want to manage libraries it becomes more helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With