Golang Package Manager: GO Module

Akash Jain
4 min readMar 21, 2020

Before GO 1.11 version, there were no official package manager of golang but there were a lot of CLI introduced by the open source community to manage go packages like dep, glide, gopkg.in etc

In 1.11 version, Go introduced their official package manager Go Module.

Previously Google was thinking of some other name like version go (vgo) and then later they all agreed with go module. Firstly understand what is module?

Suppose we have go project which has path `github.com/akashjain132/taxpayer` and we are importing many packages like

import (
fmt
net/http
github.com/gorilla/mux
github.com/sirupsen/logrus
github.com/akashjain132/taxpayer/invoice
)

Packages are divided into three categories

  • Standard Packages: fmt, net/http etc all are standard packages which are maintained by golang itself.
  • Application Packages: github.com/akashjain132/taxpayer/invoice is application packages that are managed by the developers.
  • External Packages: github.com/gorilla/mux, github.com/sirupsen/logrus are external packages that we have to download from the internet.

Go module considers only external packages. Suppose you have downloaded one external package “github.com/pmezard/go-difflib”. This package has no dependency on any other external package then we can call it a module.

Another example: “github.com/pkg/errors This package depends on two other external packages “golang.org/x/crypto and “golang.org/x/syn”, it means all combined packages make a module

So we can say in simple words that

A collection of packages with potential dependencies is called a module.

Go module

How to start Go Module

$ go mod init

Run this command in your project root directory and it will create two files go.mod and go.sum. We will see go.sum file later, the only thing that is crucial for now is go.mod

Go.mod looks like

module github.com/akashjain132/taxpayergo 1.14

Go treats your project as a module. The module key is the first word in go.mod file which tells the compiler your module name.

Total 4 directives that we can use in go.mod file:

  • Module
  • Require
  • Replace
  • Exclude

Before jumping into go.mod file content, first get familiar with new ENV variables. You must have heard the GOPATH env variable, it has the path where all Go related code lives.

$ echo $GOPATH/Users/akashjain/web/go

If we want to create a new project in golang we must have all code inside the GOPATH folder otherwise it won’t compile.

Go introduces a new env variable in 1.11 version which is GO111MODULE. The default value of this env variable is “auto”. The possible value of this env variable is “on”, “auto” and “off”.

If its “on” (go module is enabled) then go compiler ignores GOPATH and now you can put your go code anywhere and your project root folder must have go.mod and go.sum files. With “off” value (go module is disabled) you are restricted to put your code inside GOPATH and the compiler will not take care of the go.mod file and “AUTO” will automatically check your code path and behave accordingly and if they found go.mod and go.sum file, then the compiler will behave as go module is enabled.

Now let’s write a code in main.go file

We are using lorgus external package in our code, now just do

$ go run main.goHello world

And now see go.mod file

module github.com/akashjain132/taxpayergo 1.14Require (
github.com/sirupsen/logrus v1.4.2
)

Go run command adds all required external packages that have been used in a project with the latest tag. If you want to add a specific tag then use go get command.

Syntax: go get module@<tag>go get github.com/sirupsen/logrus@v1.4.2

Suppose that package hasn’t released any tag, then it will get the latest commit from the master branch. If you want to get an update from any other branch, mention that branch name

go get github.com/sirupsen/logrus@<branch name> // default: master branch

And if you want up to particular commit

go get github.com/sirupsen/logrus@<Commit ID>

Till now we have learnt two directives of go.mod file i.e., module and require. Let's go further to see other directives.

Replace directive is used to replace a particular package with other package, let’s have a look at go.mod file

This mod file will download logrus module of version v1.4.1 instead of v1.4.2. Now suppose that we have changed the whole package with some other package

This mod file will download the seelog package instead of logrus package.

Exclude directive is used to exclude a particular package to download, let’s have a look in go.mod file

Now go compiler tries to download logrus v1.4.1 but due to exclude statement it will not download that version so complier will try to look higher version and download logrus v1.4.2

We have learnt about the go module file, now let see how it works

When we run go command for a test, build or run, it reads the go.mod file and search the package locally, if it’s not present there then it will download the package from the internet.

Now one question arises here that, if compiler already found package locally then how will it make sure that anyone has touched that package or not?

So, to check that, go module have one more file go.sum, it looks like

Here in front of each package name, we have some hash value which was created by the compiler. This hash was created by using every line of that package. So, when the compiler reads go.mod file and found it locally then it creates a hash and matches with go.sum file and that’s how they verify that package is not modified by anyone.

I hope you are now familiar with the basic go module. You can visit Go Modules for more information.

--

--

Akash Jain

Love to write code and discuss technology | If you explain to others in simple words it means you know it very well — akashjain132@gmail.com