Manage Go dependencies using Glide

Glide is a Go package management tool, like npm in NodeJS. Let’s create a simple example and see how it works.

Create the project inside $GOPATH

The project folder has to be inside $GOPATH in order to resolve the Go package paths. In this example, the project root folder is $GOPATH/src/gitlab.com/ykyuen/glide-example.

A hello world Go program

Let’s create a simple Go program.

main.go

1
2
3
4
5
6
7
package main

import "fmt"

func main() {
  fmt.Println("hello world")
}

Build and run

1
2
3
[[email protected] glide-example]$ go build -o hello
[[email protected] glide-example]$ ./hello
hello world

Add a Go dependency

dustin/go-humanize is a helpful Go package to format number, string and time. Let’s update our Go program as follow.

main.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import humanize "github.com/dustin/go-humanize"
import "fmt"

func main() {
  fmt.Println("hello world")
  fmt.Printf("That file is %s.\n", humanize.Bytes(82854982)) // That file is 83 MB.
  fmt.Printf("You're my %s best friend.\n", humanize.Ordinal(193)) // You are my 193rd best friend.
  fmt.Printf("You owe $%s.\n", humanize.Comma(6582491)) // You owe $6,582,491.
}

Now if we try to build it, it will throws the following error.

1
2
3
4
[[email protected] glide-example]$ go build -o hello
main.go:3:8: cannot find package "github.com/dustin/go-humanize" in any of:
  /home/ykyuen/tools/go1.8.4/src/github.com/dustin/go-humanize (from $GOROOT)
  /home/ykyuen/go/src/github.com/dustin/go-humanize (from $GOPATH)

This is because we haven’t downloaded the dustin/go-humanize. Without using Glide, we could solve this build error by running the go get command.

1
go get github.com/dustin/go-humanize

But in this case, anyone who checkouts the project has no idea what packages are needed in order to build the program. If you have already run the go get command, delete the package before proceeding.

The Glide way

Create the glide.yaml

The glide.yaml could be generated by the glide create command. It will scan the Go src files and include all the dependencies needed. Here is the output of this example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[[email protected] glide-example]$ glide create
[INFO]  Generating a YAML configuration file and guessing the dependencies
[INFO]  Attempting to import from other package managers (use --skip-import to skip)
[INFO]  Scanning code to look for dependencies
[INFO]  --> Found reference to github.com/dustin/go-humanize
[INFO]  Writing configuration file (glide.yaml)
[INFO]  Would you like Glide to help you find ways to improve your glide.yaml configuration?
[INFO]  If you want to revisit this step you can use the config-wizard command at any time.
[INFO]  Yes (Y) or No (N)?
Y
[INFO]  Looking for dependencies to make suggestions on
[INFO]  --> Scanning for dependencies not using version ranges
[INFO]  --> Scanning for dependencies using commit ids
[INFO]  Gathering information on each dependency
[INFO]  --> This may take a moment. Especially on a codebase with many dependencies
[INFO]  --> Gathering release information for dependencies
[INFO]  --> Looking for dependency imports where versions are commit ids
[INFO]  No proposed changes found. Have a nice day.

glide.yaml

1
2
3
package: gitlab.com/ykyuen/glide-example
import:
- package: github.com/dustin/go-humanize

Download the Go dependencies to the vendor folder

Next, we execute the glide install command to download the dependencies.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[[email protected] glide-example]$ glide install
[INFO]  Lock file (glide.lock) does not exist. Performing update.
[INFO]  Downloading dependencies. Please wait...
[INFO]  --> Fetching updates for github.com/dustin/go-humanize
[INFO]  Resolving imports
[INFO]  Downloading dependencies. Please wait...
[INFO]  Setting references for remaining imports
[INFO]  Exporting resolved dependencies...
[INFO]  --> Exporting github.com/dustin/go-humanize
[INFO]  Replacing existing vendor dependencies
[INFO]  Project relies on 1 dependencies.

This will generated the glide.lock files and the vendor folder which contains the dustin/go-humanize package. The glide.lock file contains the version of the package. It could be a tag or a git commit hash.

glide.lock

1
2
3
4
5
6
hash: de8aada0e0453f13dc438db5fb412db797d701d6afeadcc052c477fd55e01aa8
updated: 2017-12-04T23:20:53.616704682+08:00
imports:
- name: github.com/dustin/go-humanize
  version: 8929fe90cee4b2cb9deb468b51fb34eba64d1bf0
testImports: []

Update dependency’s version

The 8929fe9 commit is quite outdated. We could modify version in the glide.lock file and run glide install again to get the desired version of your package.

glide.lock

1
2
3
4
5
6
hash: de8aada0e0453f13dc438db5fb412db797d701d6afeadcc052c477fd55e01aa8
updated: 2017-12-04T23:20:53.616704682+08:00
imports:
- name: github.com/dustin/go-humanize
  version: bb3d318650d48840a39aa21a027c6630e198e626
testImports: []

1
2
3
4
5
6
7
8
[[email protected] glide-example]$ glide install
[INFO]  Downloading dependencies. Please wait...
[INFO]  --> Found desired version locally github.com/dustin/go-humanize bb3d318650d48840a39aa21a027c6630e198e626!
[INFO]  Setting references.
[INFO]  --> Setting version for github.com/dustin/go-humanize to bb3d318650d48840a39aa21a027c6630e198e626.
[INFO]  Exporting resolved dependencies...
[INFO]  --> Exporting github.com/dustin/go-humanize
[INFO]  Replacing existing vendor dependencies

Build and run again

1
2
3
4
5
6
[[email protected] glide-example]$ go build -o hello
[[email protected] glide-example]$ ./hello
hello world
That file is 83 MB.
You're my 193rd best friend.
You owe $6,582,491.

Check in the vendor folder?

For NodeJS projects there is a common practice that we will ignore the node_modules folder in the code repository. On the other hand, the Go community has a different point of view.

There isn’t an absolute answer. Pick the option which you feel more comfortable.

Other concerns

When the project is getting bigger, glide might take quite a while to work as the dependency tree is getting bigger and bigger. In addition, it’s hard to manage to the dependency’s version.

You might want to consider using a new dependency management tool called dep as suggested by the Glide team. dep has a growing popularity and in active development. Do take a look on the dep’s project status and pick the one which you feel more comfortable.

Summary

  • Project folder has to be under $GOPATH.
  • Dependencies would be included automatically by scanning all the source code.
  • Dependency’s version is managed by glide.lock.
  • Commit the vendor folder or not is still an open question.
  • Performance issue when dependency tree getting bigger.
  • Complete example is available on gitlab.com.