Introduction | change with the development of the language and scene, GOPATH caused by compiler dependent and internal since the issuance of the certificate, the security audit problems appeared, along with the official launch of the Go Modules gradually perfect, the user has a new choice. This article will take you through learning and using Go Modules from zero. InfluxDB/OpenCensus Contributor and Golang code Contributor

In 2020, an internal developer report of Tencent shows that Go language has become the second largest backend development language in Tencent. In Tencent, a large number of Go developers are doing business and platform development every day, and a large number of teams and projects have exposed some problems. With the emergence of Go Modules, Issues such as internal self-issued certificates and security audits are gradually being resolved. At present, the author is in charge of some problems in the use of Go programming language in Tencent Cloud. Since the beginning of 2021, I have been in charge of internal GoProxy service and the promotion of Go Modules. These technologies support Tencent cloud, wechat, Tencent Video, Tencent Games, Tencent Music, Tencent Conference and other star products. And with the company’s internal software source team, worker bee team, TRPC team and various CI teams to achieve close cooperation. In this series of articles, the author will help you start to learn and understand Go Modules.

The evolution of patterns developed by Golang

Since Go was born, users have been using the environment variable GOPATH. With the rapid development and growth of Go, the compile dependency problems caused by GOPATH have gradually emerged. Finally, in 2019, Golang celebrated its 10th anniversary, and the Google Go team began to focus on this environmental variable that had been with Golang for a decade.

The use of GOPATH

There are currently two development modes in Go, GOPATH Mode and Go Modules Mode.

Prior to Go Modules, dependency management in Go development used the GOPATH development pattern. In GOPATH development mode, the Go command uses the GOPATH environment variable to perform the following functions:

1. Run the go install command to install the binary library to GOBIN. The default path is GOBIN, and the default path is GOPATH/bin.

2. Run the go install command to install the compiled package into GOPATH/ PKG /. For example, install example.com/y/z into GOPATH/ PKG /. For example, install example.com/y/z GOPATH/pkg/example.com/y/z.a.

3. Go get to GOPATH/ SRC /, for example, example.com/y/z to GOPATH/ SRC /, for example, example.com/y/z to GOPATH/ SRC /. For example download example.com/y/z to GOPATH/ SRC /example.

The evolution of Go Modules

The GOPATH mode development mode will eventually be eliminated. Go officially adds the concept of Package Version to the whole Go development ecosystem, and then introduces the Go Modules development mode. Switching from GOPATH Mode to Go Modules is a long process that has gone through several Go releases:

  • Go 1.11 (August 2018) introduced the GO111MODULE environment variable, which defaults to Auto. If the variable GO111MODULE=off is set, the go command will always use GOPATH Mode development mode. If you set the variable GO111MODULE=on, the go command will always use go Modules development mode. If you set GO111MODULE=auto (or not), the go command line determines which mode to use based on the current working directory. If the current directory is outside of GOPATH/ SRC and the go.mod file exists in the root directory, the go command enables the Gomodule mode. Otherwise use the GOPATH development pattern. This rule ensures that all files outside of GOPATH/ SRC exist in the root directory, then go command will enable Go Module mode, otherwise use GOPATH development mode. This rule ensures that everything outside GOPATH/ SRC exists in the root directory of the go.mod file, then the go command will enable Gomodule mode, otherwise GOPATH development mode will be used. This rule ensures that all compilations using auto in GOPATH/ SRC will not be affected and that the latest Go Module development mode can be experienced in other directories.

  • Go 1.13 (August 2019) tweaks the restriction on GOPATH/ SRC in GO111MODULE= Auto mode, if a codebase is restricted in GOPATH/ SRC, if a codebase is restricted in GOPATH/ SRC, If a code base is in GOPATH/ SRC and the go.mod file exists, the go command enables Module development mode. This allows users to continue to organize their checkout code in an import-based hierarchy, but use modules for individual repository imports.

  • Go 1.16 (February 2021) will have GO111MODULE=on as the default, enabling Go Module development mode by default, meaning that GOPATH development mode will be completely turned off by default. If you want to use GOPATH development mode, you can specify the environment variable GO111MODULE=auto or GO111MODULE=off.

  • Go 1.NN (???) The GO111MODULE environment variable and GOPATH development mode will be deprecated and the module development mode will be used entirely by default.

GOPATH and the Go Modules love to kill

In view of several questions you are concerned about, the author gives the following answers:

Q1: Will the GOPATH variable be removed?

A: No, the GOPATH variable will not be removed. The future deprecation of the GOPATH development pattern does not mean the removal of the GOPATH environment variable. It will remain in place for the following purposes:

  • The go install command installs binary files to the GOBIN directory. The default location is GOBIN, the default location is GOBIN, and the default location is GOPATH/bin.

  • The go get command caches the downloaded modules to the GOMODCACHE directory. The default location is GOMODCACHE, the default location is GOMODCACHE, and the default location is GOPATH/ PKG /mod.

  • The go get command caches the downloaded checksum data to the $GOPATH/ PKG /sumdb directory.

Q2: I can still be hereGOPATH/src/import/pathCreate a code base in?

A: Yes, many developers use this file structure to organize their repositories. All you need to do is add the go.mod file to your repository.

Q3: What do I do if I want to test modify a dependency library that I need?

A: If you rely on unreleased changes when compiling your own project, you can use go.mod’s replace to fulfill your requirements.

For example, if you have downloaded golang.org/x/website and golang.org/x/tools to the GOPATH/ SRC/directory, then you can go to the GOPATH/ SRC/directory, Then you can add the following in GOPATH/src/golang.org/x/website/go.mod instructions to complete the replacement:

replace golang.org/x/tools => $GOPATH/src/golang.org/x/tools

Of course, the replace directive is not GOPATH aware, and downloading code to another directory will work just as well.

Use Go Modules starting at 0

  1. Create a new Go Module

So I’m going to create a new directory /home/gopher/hello, and then I’m going to go into that directory, and then I’m going to create a new file,


hello.go:

package hello

 

func Hello() string {

    return "Hello, world."

}

Copy the code

Create a test file hello_test.go:

 

package hello import "testing" func TestHello(t *testing.T) { want := "Hello, world." if got := Hello(); got ! = want { t.Errorf("Hello() = %q, want %q", got, want) } }Copy the code

Now we have a package, but it is not yet a module because the go.mod file has not been created. If you run go test in /home/gopher/hello, you can see:

 


$ go test

go: go.mod file not found in current directory or any parent directory; see 'go help modules'

Copy the code

 

The Go command line prompts that the go.mod file was not found. See Go help Modules. To do this, use Go mod init and then execute Go test:

$ go mod init example.com/hello go: creating new go.mod: module example.com/hello go: To add module requirements and sums: Go mod Tidy $go mod tidygo $go test PASS OK example.com/hello 0.020s $Copy the code

 

With that, the Module test is complete.

The go mod init command then creates a go.mod file:

$cat go.mod module example.com/hello go 1.17Copy the code
  1. Add dependencies to module

The main beauty of Go Modules is that it’s a great experience to program with code written by someone else, that is, to introduce a dependency library. Let’s start with an update to Hello. go, introducing rsc. IO /quote to implement some new functionality.


package hello

 

import "rsc.io/quote"

 

func Hello() string {

    return quote.Hello()

}

Copy the code

 

Then, test it again:

 

$ go test hello.go:3:8: no required module provides package rsc.io/quote; To add it: Go get Rsc. IO /quote $go get Rsc. IO /quote go: downloading rsc. IO /quote v1.5.2 go: Downloading Rsc. IO /sampler V1.3.0 GO: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48eAD0c go: Added golang.org/x/text v0.0.0-20170915032832-14c0d48eAD0c go: Added rsc. IO /quote V1.5.2 go: Added Rsc. IO /sampler V1.3.0 $go test PASS OK example.com/hello 1.401sCopy the code

 

Starting from Go 1.7, Go Modules start to use lazyloading, and update dependent libraries manually as prompted.

The Go command will parse and pull the specified dependent version from the go.mod file. If the specified version is not found in go.mod, the command will prompt the user to add it. The go command will then parse the Latest stable version and add it to the go.mod file. IO /quote dependencies are not found in the go.mod file, so the user is instructed to obtain the latest version. IO /quote: rsc. IO /quote: rsc. IO /quote: rsc. IO /sampler: golang.org/x/text Indirect dependent references are also recorded in the go.mod file, marked with an indirect annotation.

 

$cat go.mod module example.com/hello go 1.17 require (golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect Rsc. IO/indirect rsc. IO /sampler v1.3.0 // Indirect)Copy the code

 

Running the go test command again will not repeat the above work because go.mod is up to date and the required dependencies have been downloaded to the machine (in $GOPATH/ PKG /mod) :

 

$go test PASS OK example.com/hello 0.020sCopy the code

 

Note that while the Go command is quick and easy to add new dependencies, it is not without cost.

As mentioned above, adding a direct dependency to a project can introduce other indirect dependencies. The go list -m all command lists all the dependencies that the current project depends on:

$go list -m all example.com/hello golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c rsc. IO /quote v1.5.2 RSC. IO/sampler v1.3.0Copy the code

 

In the output of the Go List, you can see that the current module, also known as the Main Module, is displayed in the first line, and then the others are sorted by Module path. The version number v0.0.0-20170915032832-14c0d48eAD0c that depends on golang.org/x/text is a pseudo version number, which is one of the Go versions and refers to an untagged COMMIT.

In addition to the go.mod file, the go command also maintains a file called go.sum, which contains the encrypted hash values for each version.

 

$cat go.sum golang.org/x/text v0.0.0-20170915032832-14c0d48eAD0c h1:qgOY6WgZO... $cat go.sum golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZO... Golang.org/x/text v0.0.0 c0d48ead0c/go - 20170915032832-14 mod h1: Nq... RSC. IO/quote v1.5.2 h1: w5fcysjrx7yqtD/aO + QwRjYZOKnaM9Uh2b40tElTs3... RSC. IO/quote v1.5.2. / go mod h1: LzX7hefJvL54yjefDEDHNONDjII0t9xZLPX... RSC. IO/sampler v1.3.0 h1:7 uvkifmebqhfdjd + gZwtXXI + RODJ2Wc4O7MPEh/Q... RSC. IO/sampler v1.3.0 / go mod h1: T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9...Copy the code

 

The Go command uses go.sum to ensure that the library code downloaded is the same as the first one, thus ensuring that the project does not have any exceptions. Therefore, both go.mod and go.sum should be uploaded to a version control system such as Git.

  1. Update the rely on

From the output of the go list -m all command above, you can see that a pseudo-version number is used in the library golang.org/x/text. First, update this version to the latest stable version:

 

$go get golang.org/x/text go: downloading golang.org/x/text v0.3.7 go: Upgrade upgrade golang.org/x/text v0.0.0-20170915032832-14c0d48eAD0c => v0.3.7 $go test PASS OK example.com/hello 0.013sCopy the code

 

The test can still pass, then run go list -m all again:

 

$go list -m all example.com/hello golang.org/x/text v0.3.7 rsc. IO /quote v1.5.2 rsc. IO /quote v1.3.0 $cat go.mod Module example.com/hello go 1.17 require (golang.org/x/text v0.3.7 // indirect rsc. IO /quote v1.5.2 // indirect Rsc. IO /sampler V1.3.0 // Indirect)Copy the code

 

Go unified the dependency management of many third parties in the Go ecosystem through the dependency management of Go Modules, and it is highly integrated in the Go command line, without additional installation and use by developers. At present, Go Modules have been supported in the current maintenance version of Go. If you haven’t already switched to Go Modules, it’s highly recommended that you start using it, as it offers great features and guarantees in terms of team development experience, performance, and security.