Go Modules for Package Management

Reading Time: 8 minutes

Go 1.11 introduces Go modules for better package management that allows dependencies to be located outside of the $GOPATH/src folder.

Package management is an essential key for every project set up to improve delivery time for developers. Programming languages like Python, Node.js, etc. have standard package managers which are used extensively by developers. These package managers help in downloading, updating, or removing project dependencies quickly and efficiently.

In this blog, we will cover:

  • What is Golang?
  • Advantages of Golang
  • What is a Go module?
  • Challenges before the Go module
  • Features of Go module
  • Commands for Go module
  • GOPATH
  • Package vs Module
  • Prerequisites
  • Hands-on
  • Conclusion

What is Golang?

Go, often known as Golang, is a Google-developed open-source, compiled, and statically typed computer language. It’s designed to be simple, fast, readable, and efficient, making it a popular choice for developers. Moreover, it is concurrent in nature, which means it can run multiple tasks at the same time.

Go finds its use in backend programming, game development, cloud-based programming, data science, etc. It is also used for making command-line tools.

Google, Netflix, Twitch, Ethereum, Dropbox, Kubernetes, Docker, Heroku, and a slew of other digital heavyweights use Go today.

Advantages of Golang

  • Developers can build projects in the directory of their choice with the help of Go modules.
  • Testing Support is a feature that allows us to run multiple unit tests on our code.
  • There is no need to include any header files in the programme because of the Golang Package system, which allows you to use the functionality of other files.
  • It includes statically typed programming, which includes compilation, type conversion, and comparison.
  • It comes with a powerful standard library that assists developers in creating projects in both an effective and simpler manner.
  • Error checking is provided by the Go compiler, which can identify variables that have been unused, missing or imported packages that are required to run, and mistyped or invalid operations.

What is a Go module?

Go or Golang, written in C, is an Algorithmic Language with features like Garbage Collection, Memory Safety, Statically Typing, and CSP-Style Concurrent Programming.

Go Modules, like npm in Node.js and pip in Python, are now the default manner of handling dependencies in Golang. Version 1.11 added Go modules, a feature to manage the libraries a Go project depends on. Go modules is a built-in dependency versioning and management feature in Go. It consists of a collection of Go packages and libraries or projects.

In the early versions of Go, developers had to add their dependencies in the GOPATH directory. With the help of the Go modules, developers can create projects in any directory of their choice.

In a Go project, Go Modules introduce two new files:

  • go.mod gives the name of the module, as well as its dependencies and minimum versions.
  • go.sum is a dependency lock file that is generated automatically.

Both files are contained in the project’s root directory.

Challenges before the Go module

When it comes to Golang, the early versions had no dependency management system. go get was the command used to download such dependency in our GOPATH directory. It looks a bit odd because, in the case of any major updates in a particular package, there is a high probability that our application would break.

Later on, third parties tools like dep and vendoring came along, but the Go language itself had no internal tool to resolve this.

With Go 1.11, Go modules were introduced. The advent of Go Modules has completely changed the landscape of Golang dependency management. The package management system resolves dependency versioning concerns, ensures explicit dependency information, and simplifies other dependency management duties.

Features of Go module

Go Modules for Package Management
  • The Go module can also store dependencies in the vendor directory, allowing different projects to use various versions of the same packages.
  • There is no need to install additional tools & software because Go Modules is a built-in function.
  • Automatically check for dependencies when doing build, run, or test.

Commands for Go module

Go Modules for Package Management
  • go mod init: creates a whole new module in the current directory.
  • go mod tidy: fixes missing modules and removes others who aren’t in use.
  • go mod download: downloads modules to your device’s cache.
  • go mod vendor: this creates a vendored copy of dependencies.
  • go mod graph: prints module requirement graph
  • go mod verify: verifies dependencies have expected content
  • go mod why: explains the need for packages or modules

GOPATH

Earlier projects had to be created inside the $GOPATH, which is an environmental variable that points to the directory where your Go workspace exists before Go Modules were introduced.

Go manages your project files, and dependencies, and installed binaries in this workspace.

When it comes to setting up a development environment and understanding how the compiler manages dependencies for a project, the use of $GOPATH mechanisms proved to be restrictive and provided a bit of a learning experience for Go beginners.

Package vs Module

A package is a directory of .go files, and it is the basic building block of a Go program. Packages help to organize code into reusable components.

On the other side, a module is a collection of packages with built-in dependencies and versioning. A module comes with two additional files go.mod and go.sum.

Prerequisites

  1. Go installed in your system
    a. Version should be 1.11 or more.

Hands-on

Go Modules for Package Management

Creating a new Go module

We will start with creating a new directory that can be located anywhere. As mentioned earlier, with the release of Go modules, we can create a go project anywhere other than the GOPATH directory. 

Let us create a project directory and switch to it using the command.

Next, we will create a module directory with the name as newmodule.

Note: The name of the project directory and the module are usually the same. 

Now, in the project directory, run the below command.

The module must then be configured. For this, the go tool has provided us with a command to initialize the module go mod init <module_name>. To execute this command, we should navigate to our newmodule directory.

If we open the go.mod file, we will see the below output –

Go Modules for Package Management

The last line – `go 1.17`,  specifies the version of Go used in creating the module. The first line mentions the name of our module passed to go mod init command. It tells Go to search our newmodule in this module directly and not anywhere else whenever we import this newmodule in our .go files.

This file expands when more dependencies get added to our project. Currently, our module does nothing. Let us add a small code to see how modules work.

First Go module code

Let’s create a main.go file in our newmodule directory. The main.go file is commonly used to specify the starting point of a program.

We will try to print My first Go module in the main.go file.  Let us add the below code:

The important point to note here is in Go every directory is a package in itself. In our file, we have added the main package which specifies that this should be considered as binary and must be compiled into an executable file.

The main function carries an important role too. When Go sees a function named as main inside the main package, it gets executed first. The main function is the entry point for our Go application.

To run our Go program, we can directly use go run main.go or create an executable binary using go build. Let us run our new module directly using the go run command.

Go Modules for Package Management

To create a binary, we will execute the go run command. It should not raise any errors. This will create a newmodule binary in our newmodule directory. We can execute this binary using the ./newmodule command and it should print the required result.

Here we have verified our Go module is functioning correctly without any errors and it is available for adding a package.

Adding a package to our newmodule

As mentioned in the Package versus Module section, a module can contain multiple packages. We can also add a package inside another package. Let us create a package named newpackage in the newmodule directory and add a newpackage.go file inside it.

Go Modules for Package Management

In our newpackage.go file, let us add the below code.

Go Modules for Package Management

The first line mentions the package name. Notice the function name PackageMessage is capitalised. It is important because the PackageMessage function should be available to any outside program. Once this file is set we need to test this behaviour in the newly created module.

We navigate back to our newmodule directory and import newpackage.go in our main.go file. We will call the PackageMessage function inside our main.go and run this module.

Go Modules for Package Management

We execute the above code using go run main.go and should observe the output as below:

Go Modules for Package Management

Or we can also run go build, which will regenerate the binary, and when we run ./newmodule we should see the same output as above.

The import path for a newpackage is newmodule/newpackage. The newmodule is the same module name, we set in the go.mod file.

Adding remote module as a dependency

Tests are extremely important when working with any programming language. In Go, we have one such testing framework as Ginkgo. So we can add this to our module using the go get command.

Go Modules for Package Management

When we run the go get command, it first looks for the ginkgo library on Github. By default, it downloads the latest code since we have not mentioned any specific version.

Once the command is executed successfully, we open the go.mod file and observe a new required block added. Go also adds the version which was downloaded when executing the go get command. The // indirect line specifies Indirect dependency, which is a dependency that wasn’t listed in go.mod of your direct dependency but is still required. 

A new file go.sum also gets created after running the go run command. This file contains information used by Go to record specific hashes and versions of dependency. This makes sure the dependencies are consistent even if they are installed on different machines.

If we want to install a dependency of a particular version or commit we can execute the below commands.

Removing a Go module

Removing any unused Go module is easy by using a terminal. We just need to run the below command in our project directory.

Once this command is successfully executed, it will remove any unused dependencies and update the go.mod file. The command also adds any missing dependencies, like an external package that we wanted to fetch failed first with the go get command. 

Conclusion

In this blog, we’ve explored how Go Modules are implemented for Golang package management. The Go module feature is a big relief for developers which enhanced the package dependency management. It has simplified the installation, up-gradation, and removal of dependencies without relying on external tools. Stay tuned to keep getting all updates about our upcoming new blogs on different technologies.

Meanwhile…

Keep Exploring -> Keep Learning -> Keep Mastering

This blog is part of our effort towards building a knowledgeable and kick-ass tech community. At Workfall, we strive to provide the best tech and pay opportunities to AWS-certified talents. If you’re looking to work with global clients, build kick-ass products while making big bucks doing so, give it a shot at workfall.com/partner today.

Back To Top