Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it really necessary to place Go source code in $GOPATH/src?

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?

like image 407
Lone Learner Avatar asked Apr 19 '17 14:04

Lone Learner


People also ask

Do Go projects have to be in Gopath?

$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.

What is in the src directory Golang?

src contains Go source files, and. bin contains executable commands.

Do I need to use Gopath?

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.

What is a Go source file?

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.


3 Answers

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
$ 
like image 143
peterSO Avatar answered Oct 06 '22 20:10

peterSO


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:

  • Projects grow, and by 10K or 100K lines you really need to organize.
  • Projects often turn out to contain reusable tools, and packages let other projects import them separately.
  • Packages let you track and control what code has access to what other code and variables. For instance, private names in one package aren't accessible for other packages, so you know you can mess around with that private stuff without breaking code outside the package, and you know that no code outside is futzing with private fields/variables or calling private code behind your back.
  • Packages minimize namespace collisions, i.e., you can have gzip.Reader and io.Reader. If you choose your names right, packagename.ThingName can make code read naturally.
  • Packages can be recompiled, tested, etc. individually, which keeps your edit/build/test cycle faster.
  • In Go specifically, packages enforce some other things about your code organization, like no cyclic dependencies (if A imports B, B doesn't directly or indirectly import A) and that packages under /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.

like image 3
twotwotwo Avatar answered Oct 06 '22 21:10

twotwotwo


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.

like image 2
John Weldon Avatar answered Oct 06 '22 20:10

John Weldon