Golang Modules Tutorial
Tags: go, tutorial
Published: 2020-11-24 03:03:16

## Introduction

Software dependency management is an essential feature to make development process easier. Dependency management can be found in many programming languages such as npm for NodeJS, composer for PHP and others. In Golang, dependency management can be done using Golang Modules. Golang Modules introduced since Go 1.11 and Go 1.12 is released.

This tutorial will cover many things:

- Initiate the Golang Module
- Add a Dependency
- Release a Dependency
- Update a Dependency

> Requirements needed for using Golang Modules is Go 1.11 or above. `git` is also required.

## Initiate the Golang Module

> Before initate a Golang Module, make sure to create a new repository in Github or other version controls (e.g. Gitlab). Then clone the repository into your local machine oustide `GO_PATH`.

Golang Module can be used outside `GO_PATH`, to initiate a Golang Module, use this command:

```
go mod init github.com/nadirbasalamah/go-simple-module
```

The command structure above looks like this:

> The domain and module name must same with repository name that already created

```
            // domain                // module name
go mod init github.com/nadirbasalamah/go-simple-module
```


After module has been initiated. The `go.mod` file is created. `go.mod` file contains many libraries or dependencies that used in application.

> Golang module can be created without specifying the domain. this is the example: `go mod init my-go-app`.


## Add a dependency

Adding a dependency to application can be done using `go get` command. Sometimes many dependencies installation using `go get -u` to allow an update in the dependency. This command add a new dependency called `tokenizer` to do a basic text preprocessing.

```
go get -u github.com/sugarme/tokenizer
```

The github repository of `tokenizer` can be checked [here](https://github.com/sugarme/tokenizer).

After dependency is added, let's implement the basic text preprocessing with `tokenizer` in a file called `simple.go`.

```go
package go_simple_module

import (
	"fmt"
	"log"

	"github.com/sugarme/tokenizer/pretrained"
)

// Preprocess returns preprocessed text
func Preprocess() []string {
	tk := pretrained.BertBaseUncased()

	sentence := `The quick brown fox jumps over the [L A Z Y D O G]`
	en, err := tk.EncodeSingle(sentence)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("tokens: %q\n", en.Tokens)
	return en.Tokens
}
```

The code above basically do a text preprocessing in a given text in `sentence` variable and return the preprocessing result in a slice of string.

## Release a dependency

The functionality of text preprocessing is added. Before releasing a dependency that already created. Let's create a new tag `v1.0.0` for our module with this command:

```
git tag v1.0.0
```

After the tag is created, push the local changes with the following tag with this command:

```
git push origin --tags
```

The release step is finished. As additional note, the Golang modules is integrated very well with Git so the release step is very simple by using the git commands.

To use the dependency that already created, the step is similiar by using `go get` command followed with your remote repository name.

```
go get github.com/nadirbasalamah/go-simple-module
```

Then use the dependency in `main.go` file.

```go
package main

import (
	"fmt"

	go_simple_module "github.com/nadirbasalamah/go-simple-module"
)

func main() {
    // Usage example
	fmt.Println(go_simple_module.Preprocess())
}
```

Output:

```
tokens: ["the" "quick" "brown" "fox" "jumps" "over" "the" "[" "l" "a" "z" "y" "d" "o" "g" "]"]
[the quick brown fox jumps over the [ l a z y d o g ]]
```

## Update a dependency

There is a case when dependency needs to be updated for some reasons. For example bug fixes, adding new features, etc. In this case, let's add a parameter in `Preprocess()` function in our dependency that already created.

```go
func Preprocess(sentence string) []string {
	tk := pretrained.BertBaseUncased()
	en, err := tk.EncodeSingle(sentence)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("tokens: %q\n", en.Tokens)
	return en.Tokens
}
```

Based on that code, the `Preprocess()` function can preprocess any sentence given in the parameter, before update our dependency, let's change the version of the dependency in `go.mod` file by adding `v2` sentence.

```
module github.com/nadirbasalamah/go-simple-module/v2
```

This change is needed to maintain the old version of the dependency so the old version still available and to avoid the incompatible issue when the newest version of the dependency is released.

To release a newest version of the dependency, use the `git tag` command.

```
git tag v2.0.0
```

Then release it with `git push origin --tags` command. To use the newest version of our dependency, use the `go get` command followed with the remote repository name that use the newest version.

```
go get github.com/nadirbasalamah/go-simple-module/v2
```

The usage example in `main.go` can be seen below:

```go
package main

import (
	"fmt"

	go_simple_module "github.com/nadirbasalamah/go-simple-module/v2"
)

func main() {
	fmt.Println(go_simple_module.Preprocess("testing with parameters"))
}
```

Output:

```
tokens: ["testing" "with" "parameters"]
[testing with parameters]
```

## Summary

Golang modules is a dependency management feature that available since Go 1.11. Golang modules is integrated very well with Git so the release and update a dependency mechanism can be done conveniently.

## Sources

The additional sources for learning Golang Modules can be checked below:

- [Golang blog about Golang Modules](https://blog.golang.org/using-go-modules)
- [Golang documentation](https://golang.org/doc/tutorial/create-module)
- [Resources for Golang dependencies](https://pkg.go.dev/)

I hope this article is helpful for learning Golang Modules. If you have any thoughts or feedbacks, you can write it in the discussion section below.