Go Private Module

Thanh Pham / Sun 24 Sep 2023

Sooner or later as a Go developer, you will need to build a module for reusing common code across the applications. If your module is public, that's quite straight forward, just create a public repository in GitHub or GitLab, make sure `go.mod` is defined correctly and you're ready. But if your module is private, there are some steps that need to be done so that Go Module works correctly. This post is all about initializing and setting up a private Go module.

Init Module With Git Full Qualify Domain Name

Normally you should name your module to match with where your repository is located in your Git server.

If your your code located at: `https://gitlab.mycompany.com/my-module`, your `go.mod` should be:

module gitlab.mycompany.com/my-module

go 1.21.0

Since your module name already included Git full qualify domain name, Go Module know exactly where to download your module, hence you can use the module name directly in other modules:

module my-application

go 1.21.0

require gitlab.mycompany.com/my-module v0.0.1

Init Module With Custom Name

If for some reasons, you don't want to include the full qualify domain name in your module name, you can define your module as below:

module my-module

go 1.21.0

And to use it, you need to tell Go Module where to download your module. One of the solution is using `replace` directive:

module my-application

go 1.21.0

require my-module v0.0.1

replace my-module => gitlab.mycompany.com/my-module v0.0.1

And if during the development, you want to use local/unpublished code of `my-module` right away in other module for testing, you can also use the `replace` directive to point directly to where the module is located:

module my-application

go 1.21.0

require my-module v0.0.1

replace my-module => ../relative/or/absolute/path/to/my-module

Local Development

To build the code locally, the first step is to tell Go Module that your module is private so that it doesn't use its proxy or checksum database against your module.

This can be done by using the `GOPRIVATE` environment variable. And if your company Git server doesn't use certified certificates, you might consider to use `GOINSECURE` to ignore certificates verification issues while downloading the module:  

go env -w GOPRIVATE=gitlab.mycompany.com/*
go env -w GOINSECURE=gitlab.mycompany.com/*

Go Module uses Git under the hood. Hence you need to set up your Git client to allow downloading your module without prompting for username/password. This can be done by set an environment variable named `NETRC` or a file `.netrc` at your home directory:

machine <url> login <username> password <token>

After finishing this step, you're ready to `go get` your private module


You can apply the same steps of local development to the CI/CD pipeline. Below is an example of using GitLab CI:

  GOPRIVATE: gitlab.mycompany.com/*
  GOINSECURE: gitlab.mycompany.com/*

    name: golang:1.21.0
    pull_policy: if-not-present
    - printf "machine gitlab.mycompany.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc
    - go build ./...

And now your pipeline is ready to download your private module.

Next In
Cancellable Functions

A combination of channel and Context is a very powerful tool for cancellable functions.