GoLang Modules & Binaries: Go Get vs Go Install

GoLang Modules & Binaries: Go Get vs Go Install

A simple example of Go modules and binaries

Introduction

Go uses modules as a way to package code and manage dependencies. It can be quite confusing when first starting the language to understand exactly how Go binaries and modules are installed and handled, and this short guide attempts to explain it with a few simple examples.

First, the basics:

  • GOPATH - This environment variable (use 'go env' to list all) is the path to the location that installed Go modules sit

  • GOROOT - This environment variable is the installation path of your Go installation, and holds your Go binary plus any default packages such as fmt

  • GOBIN - This is generally not set and defaults to $GOPATH/bin, and stores binaries that get installed via go install

So what is the difference between 'go get' and 'go install'? The documentation is not very clear and it certainly takes some digging.

'go get' is for installing modules. You will notice this when you try to import a module that is not installed and do 'go run main.go', it will prompt you to install the dependency via 'go get'.

'go install' is for installing binaries, not packages.

It's important to remember that go libraries are added via 'go get' to a project and are tracked in the the go.mod file. Go binaries are for use external to go development. Any user without go installed can run your binary. You could even 'go install' a binary, completely uninstall go, and still run the binary. 'go install' is essentially just 'go build' with the added fact that it places the executable in your $GOPATH/bin directory.

Demo

Now let's build it ourselves. We will be creating 2 projects:

  • go-module

  • go-binary

The idea is to install our module for use in the binary, then install the binary and see what happens.

go-module:

  1. Create a new folder titled 'go-module'

  2. Run 'go mod init github.com/[username]/go-module'

  3. Add the file hello.go with the following contents:

    1.  package hello
      
       import (
           "fmt"
      
           "github.com/pkg/errors"
       )
      
       func Hello() {
           fmt.Println(errors.New("Testing Module!"))
       }
      
  4. Save the file, upload to a git repository

  5. Run 'go get github.com/pkg/errors'

    1. Notice this will install the errors package in your $GOPATH directory under $GOPATH/pkg/mod/github.com/pkg/errors. This is an example of installing a module

go-binary

  1. Create a new folder titled go-binary

  2. Run go mod init github.com/[username]/go-binary

  3. Add the file main.go with the following contents:

    1.  package main
      
       import (
           "fmt"
           module "github.com/[username]/go-module"
       )
      
       func main() {
           fmt.Println("tesT")
           module.Hello()
       }
      
  4. Save the file, upload to a git repository titled github.com/[username]/go-binary

  5. Run go get github.com/[username]/go-module

    1. You have just imported your first custom module

Now how to do we install this binary? First, a neat little command is go list -f '{{.Target}}' , which will show you the install path of the executable one you install it. You can run this from your go-binary folder.

Now from a completely different terminal, run go install github.com/[username]/go-module . Notice how this build places the source code in your $GOPATH/pkg directory while also placing the executable in your $GOPATH/bin directory.

This is a simple tutorial for using go get and go install, which both can be a bit confusing for first time go users.