Skip to content

Latest commit

 

History

History
107 lines (78 loc) · 3.1 KB

1.3.1.md

File metadata and controls

107 lines (78 loc) · 3.1 KB

GOPATH - a quick detour

To gain a better understanding of how go works, we are going to rewind to February 2018, before go 1.11 was released. This info is still relevant, but hidden and expanded on in future versions of go.

Concepts

Let's take a look at how imports work on a deeper level. The go compiler is given a list of import paths and has to resolve them to folders that contain package code.

We'll begin with the built-in stdlib, and then explore remote and local packages.

go help env
go env GOROOT        # The same as `go env | grep GOROOT`
ls $(go env GOROOT)
# bin src ...

If we investigate further, we can see the "rand" package we were able to import from the "math/rand" import path.

# This is the rand package!
ls $(go env GOROOT)/src/math/rand
# We can even see the "Int" function we used
grep "func Int()" $(go env GOROOT)/src/math/rand/*

To sum it up: go tries to match up GOROOT/src with an import path.

However, on a day-to-day basis, we don't want to be working close to the go executable and standard library. Enter GOPATH.

go env GOPATH
ls $(go env GOPATH)

If the directory is empty, let's return to our previous example and download the remote "logrus" package.

go get github.com/sirupsen/logrus
ls $(go env GOPATH)/src/github.com/sirupsen/logrus

Now that logrus is downloaded, we can use it without errors in a project. Let's create a file called main.go somewhere outside of GOPATH.

package main

import "github.com/sirupsen/logrus"

func main() {
  logrus.Info("Who reads info logs?")
}

go run main.go should work, because it matches the import path "github.com/sirupsen/logrus" with the corresponding folder in GOPATH/src

Finally, a note on local packages. Remember our previously mentioned project structure?

main.go
pkg/
   example/
          file_one.go
          file_two.go
   another/
          file_one.go
          file_two.go

main.go would need an import statement similar to:

package main

import "github.com/username/project/pkg/example"

func main() {
  example.DoSomething()
}

You guessed it -- this project needs (needed) to be stored in GOPATH/src also! You would not be able to use local packages if you stored your project outside GOPATH/src, because go only knows (knew) to look in GOROOT and GOPATH.

Exercises

Create a project in GOPATH that uses a local package. Ensure you can run it.

Tips

  • If you'd like to make life harder, you can change your GOPATH by setting the env var in your rc file.
  • logrus contained no "main", so it can never be run as an executable.
  • Try running go get github.com/hashicorp/terraform, checkout GOPATH/bin. Run it.
  • Many go developers add GOPATH/bin to their path.
  • Remember the exercise from 1.1: where does go actually live? It's in GOROOT/bin.

Further Reading

In the next section, we are going to move away from go get with new features of go. But it is worth it to take a quick peak at dep to understand how package management used to work.


prev -- up -- next