In the previous article, we first introduced several package management methods of Go, and then specifically introduced a package management tool: Glide. With the release of Go 1.11, the official package management tool Go Modules became popular. Support for Go Modules was enhanced in the recent Go 1.12 release. This article will show you how to install and use Go Modules in your project.

Install and enable support for Modules

precondition

As mentioned at the beginning of this article, Go Modules is only supported since Go 1.11. Therefore, the default Go version is >= 1.11.

$go version go1.12 Darwin/AMd64Copy the code

I installed the latest version 1.12.

Activate the use

Once installed, we can activate module support in one of two ways:

  • in$GOPATH/srcCall the go command in a directory other than the current directory or any of its parent directoriesgo.modFile, and environment variablesGO111MODULENot set (or explicitly set to auto).
  • Set on the environment variable setGO111MODULE = onThen, the go command is invoked.

How to define a module

Create a go.mod file for the current project.

When the project is not in GOPATH, execute directly:

go mod init
Copy the code

Otherwise, the following error occurs:

go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'
Copy the code

Therefore, we need to activate Modules manually:

$ export GO111MODULE=on
Copy the code

Then go mod init. This transforms any existing DEP gopkg. lock file or any of the other nine supported dependencies to add require statements to match the existing configuration.

Go Mod init is usually able to automatically determine the appropriate module path using secondary data (such as VCS metadata), but if go Mod init indicates that it cannot automatically determine the module path, or if you need to override the path in some other way, You can provide the module path as an optional parameter to Go Mod init, for example:

$ go mod init modtest
Copy the code

Building blocks

When executed from the root of the module,./… The pattern matches all packages in the current module. Go Build will automatically add missing or unconverted dependencies as needed to satisfy the import of this particular build call:

$ go build ./...
Copy the code

Test module

$ go test ./...
Copy the code

Test the module as configured to ensure that it works with the selected version. You can also run tests for modules and all direct and indirect dependencies to check for incompatibility:

$ go test all
Copy the code

In actual combat

Create a project

Create the project and enter the root directory:

$ mkdir src/hello
$ cd src/hello
Copy the code

Initialize the

$ go mod init github.com/keets2012/hello
go: creating new go.mod: module github.com/keets2012/hello
Copy the code

Go mod initialization, and name the package called github.com/keets2012/hello. As you can see, the go.mod file is created together.

Implement a simple method

$ cat <<EOF > hello.go
package main

import (
    "fmt"
    "rsc.io/quote"
)

func main() {
    fmt.Println(quote.Hello())
}
EOF
Copy the code

We create a hello.go file and print out the results of the called method.

Build the execution

$go build # Build executable $./hello # Execute hello, worldCopy the code

After executing the build, we get the executable, and we execute to get the result. The go.mod file has been updated to include an explicit version of the dependencies, where V1.5.2 is the Semver flag:

$cat go. Mod module github.com/keets2012/hello require RSC. IO/quote v1.5.2Copy the code

Upgrade and downgrade dependencies

Go Get should be used for routine upgrades and downgrades of dependencies, which will automatically update the Go.mod file. Or you can just edit go.mod.

In addition, commands like Go Build, Go test, or even Go List automatically add new dependencies as needed to satisfy the import.

To view available minor and Patch program upgrades for all direct and indirect dependencies:

go list -u -m all
Copy the code

To upgrade to the latest version of all direct and indirect dependencies of the current module:

  • rungo get -uTo use the latest minor or patch release
  • go -u = patchUse the latest patch version

To upgrade or downgrade to a more specific version, go Get allows you to override version selection by adding the @version suffix or “module query” to the package argument, e.g. Go get [email protected], Go get foo@e3702BED2, Or go foo @’

semver

In the previous section, we mentioned semver. Golang officially recommends a best practice called Semver, which is short for Semantic Versioning, or Semantic Versioning, when fully written.

Semantically defined

In layman’s terms, it is a clear and readable version format that clearly reflects version information. More specific specifications are here.

As the specification states, a form like vx.y.z is clearly more intuitive than a string of hashes, which is why golang’s developers focused on this.

Why use semantic versions

Semver’s simplified version of the specification is obvious, but that alone is a bit of a weak argument. Strict versioning by Semver maximized backward compatibility and avoided the “breaking changes” golang was looking for. The two clicked, so Go Modules offers support for semantic versions.

If you are using and distributing packages without a version tag or in 1.x, you probably won’t see much of a difference, as the formats supported by the Go Mod follow Semver from start to finish, with the main differences being in v2.0.0 and later packages.

If the old software package and the new software package have the same import path, the new software package must be backward compatible with the old software package. – go modules wiki

Objects with the same name should be backward compatible. However, according to the convention of semantic versions, the occurrence of V2.0.0 must indicate a significant change, and backward compatibility may not be guaranteed.

The answer is simple: we simply append version information to the end of the package import path, for example:

Module my-module/v2 require (some/ PKG /v2 v2.0.0 some/ PKG /v2 v2.0.0 my/ PKG /v3 v3.0.1)Copy the code

The format is summarized as pkgpath/vN, where N is the major version number greater than 1. This version information also needs to be attached to the import code, such as import “some/ PKG /v2”. This changes the import path of the package without worrying about the restriction of backward compatibility for objects with the same name, because Golang believes that different import paths mean different packages. And then there are the surprises:

  • The equivalent require gopkg.in/some/pkg.v2 v2.0.0 can be used when using the gopkg.in format
  • Add after version information+incompatibleI don’t have to specify it/vN, such as:The require some/PKG v2.0.0 + incompatible

In other cases, using the V2 + version directly will cause go mod errors.

Packages of v2+ version are allowed to coexist with other packages of different larger versions (provided /vN is added), and they will be treated as separate packages.

In addition, /vN doesn’t affect your repository, you don’t need to create a repository for V2, it’s just an additional information added by the Go Modules.

Of course, if you don’t want to conform to the specification or need to be compatible with existing code, specifying +incompatible can be a reasonable choice. However, Go Modules doesn’t recommend this behavior.

Using the Vendor directory

If you don’t like the way Go Mod is cached, you can use go Mod Vendor to go back to the vendor directory used by Godep or GoVendor for package management.

Of course, this command doesn’t allow you to migrate to Go Modules from a tool like Godep. It simply downloads all the dependencies in Go. sum into the vendor directory. If you use it to migrate godep you will find that the packages in the Vendor directory are quite different from those specified by Godep, so be sure not to do this.

Use go build-mod =vendor to build the project, because in go Modules mode, Go build is shielded from vendor mechanism, so specific parameters are required to restart vendor mechanism:

go build -mod=vendor
./hello
hello world!
Copy the code

The build succeeded. When publishing, you just need to bring the vendor directory as you would with godep.

conclusion

This article mainly introduces some features and use methods of Go Modules, go Modules is the official package management tool, go language through the introduction of the concept of Module and then the introduction of go tool another mode of module-Aware mode. Under the new working mode, Module supports versioning of package dependencies.

There are also some problems with the new working mode. There are some third-party packages that are not available on the mainland via the Go Get command, the most common of which are the excellent packages at golang.org/x. Once working in a module, go Build will no longer care about the package under GOPATH or Vendor. Instead, go build will go to GOPATH/ PKG /mod to check whether there is a cache. If not, it will download a certain version of module. They often fail on the mainland. We will cover proxy configuration implementation for the Go Module in the next article.

Recommended reading

Package management tools for Go

Subscribe to the latest articles, welcome to follow my official account

reference

  1. Modules docs
  2. Explore go Modules again: Use and details