Use GoModule
English original: https: //blog.golang.org/using-go-modules
Introduction
This is the first in a series of
- 1- using GoModule (current)
- 2- migrate to GoModule
- 3- release GoModule
- 4-GoModule: v2 and the new version
Go1.11 and Go1.12 contains a preliminary GoModule support, which is a new dependency management system that can more easily and accurately manage the version information of dependencies. This article describes the basic operations required GoModule.
A module is stored in a go.mod
set of GoPackage file, go.mod
file defines the module of the module path (this module is the root path import) and the desired dependent (dependent on the other module in this module). Are each dependency in semantic version
the form as a module path
write go.mod
.
In Go1.11 when, in $GOPATH/src
a file or folder other than any parent path contains go.mod
a file, it can be used in GoModule go command. (For compatibility, $GOPATH/src
the files in the folder even if there is go.mod
a file, run at GOPATH mode.) From the start Go1.13 module mode will become the default development model.
The main contents are as follows:
- New module
- Add dependent
- Upgrade dependence
- Add a new major version of dependency
- Upgrade to a new major version dependent
- Remove the dependency unused
New module
In $GOPATH/src
addition to create a new folder and create a folder hello.go
:
package hello
func Hello() string {
return "Hello, world."
}
Then write one hello_test.go
:
package hello
import "testing"
func TestHello(t *testing.T) {
wang := "Hello, world."
if got := Hello(); got != want {
t.Errorf("Hello() = %q, want %q", got, want)
}
}
Now this package is not the module, because there is no go.mod
file, assuming that is currently in /home/gopher/hello
, run go test
'll see:
$ go test
PASS
ok _/home/gopher/hello 0.020s
$
The last line is a summary of the entire package of test. Since neither the current $GOPATH
case is not a module mode, and go find command did not use the import, so the current path has become a "fake" the GOPATH.
Now we implement go mod init
to enable module mode and the current path made of the root path module, and then execute go test
facie effect:
$ go mod init example.com/hello
go: creating new go.mod: module example.com/hello
$ go test
PASS
ok example.com/hello 0.020s
$
Now we have completed the new module, go mod init
the command generates a go.mod
file:
$ cat go.mod
module example.com/hello
go 1.12
$
go.mod
The file will only appear in the root directory module, subdirectory import path
by the module path
relative path and subdirectories composition. Assuming that there is a subdirectory world
, then here you do not need to perform go mod init
, and this package will be automatically considered to be example.com/hello
part of its conduction path for the package example.com/hello/world
.
Add dependent
The main purpose is to increase the use of others GoModule Code (ie add dependencies) experience. Now add an import in the above example:
package hello
import "rsc.io/quote"
func Hello() string {
return quote.Hello()
}
Then execute go test
:
$ go test
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
PASS
ok example.com/hello 0.023s
$
go command parses go.mod
dependent and versions listed in the file, if found go.mod
not in the import, it is automatically put in the latest version. (The latest version refers to the latest stable version or the latest tag or commit.) In this example go test
resolve to the new import-- rsc.io/quote
latest version is v1.5.2
, and it used two dependent - rsc.io/sampler
and golang.org/x/text
only directly dependent will be recorded to go.mod
:
$ cat go.mod
module example.com/hello
go 1.12
require rsc.io/quote v1.5.2
$
In go.mod
the case of up-to-date execution again go test
will not be repeated this operation, the module will be downloaded to the cache $GOPATH/pkg/mod
in.
Although the go command attention convenient, but this does not mean the end. Now module strictly dependent on go.mod
the specified name in the given version.
As described above, adding a direct dependency usually lead to other indirect dependency, execution go list -m all
can see the details of the current-dependent:
$ 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.0
$
As can be seen the current module main module
is always appears on the first line, is then sorted by the path module dependencies.
Dependencies golang.org/x/text
version v0.0.0-20170915032832-14c0d48ead0c
is pseudo-version
a, this is the version without a tag syntax for the situation.
Also go.sum
it is used as go.mod
a subsidiary, which contain various versions of the module cryptographic hashes
:
$ cat go.sum
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZO...
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.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:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/Q...
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9...
$
go command go.sum
to ensure that future downloads with the first download module has the same checksum, so in order to ensure that the project's module has not been tampered with. go.mod
And go.sum
it should be incorporated into version control.
Upgrade dependence
In GoModule, the version to version withdrawals by semantic tags. semantic version label consists of three parts: major, minor, patch, such as the major v0.1.2 is 0, minor is 1, patch 2. The following look minor version upgrade, the next section to see major version upgrade.
From go lit -m all
can see the output, currently in use golang.gor/x/text
it is no tag version, now updated to the latest version and then try tag is working properly:
$ go get golang.org/x/text
go: finding golang.org/x/text v0.3.0
go: downloading golang.org/x/text v0.3.0
go: extracting golang.org/x/text v0.3.0
$ go test
PASS
ok example.com/hello 0.013s
$
Everything is normal, then have a look go list -m all
as well go.mod
:
$ go list -m all
example.com/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0
$ cat go.mod
module example.com/hello
go 1.12
require (
golang.org/x/text v0.3.0 // indirect
rsc.io/quote v1.5.2
)
$
Dependent package golang.org/x/text
has been upgraded to the newest tag version (v0.3.0), and go.mod
also updated simultaneously. Here's indirect
comment indicates that this was not dependent on the current module directly, only being dependent on other dependencies. You can go help modules
see the details.
We will now rsc.io/sampler
look to upgrade minor version, the same execution go get
and go test
:
$ go get rsc.io/sampler
go: finding rsc.io/sampler v1.99.99
go: downloading rsc.io/sampler v1.99.99
go: extracting rsc.io/sampler v1.99.99
$ go test
--- FAIL: TestHello (0.00s)
hello_test.go:8: Hello() = "99 bottles of beer on the wall, 99 bottles of beer, ...", want "Hello, world."
FAIL
exit status 1
FAIL example.com/hello 0.014s
$
Error, indicating the new version rsc.io/sampler
is not compatible with current use, look at this package depend on the version of the list of available tag:
$ go list -m -versions rsc.io/sampler
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99
$
Used before the upgrade is v1.3.0, and v1.99.99 look so bad, then try v1.3.1:
$ go get rsc.io/[email protected]
go: finding rsc.io/sampler v1.3.1
go: downloading rsc.io/sampler v1.3.1
go: extracting rsc.io/sampler v1.3.1
$ go test
PASS
ok example.com/hello 0.022s
$
Note go get
command @v1.3.1
display parameters, usually all go get
parameters can be displayed with a version number, default to @latest
represent the latest version.
Adding new master version dependencies
Now in the care of a wash added func: func Proverb
to return a concurrent go proverb, by calling rsc.io/quote/v3
in quote.Concurrency
to achieve. First, hello.go
add func in:
package hello
import (
"rsc.io/quote"
quoteV3 "rsc.io/quote/v3"
)
func Hello() string {
return quote.Hello()
}
func Proverb() string {
return quoteV3.Concurrency()
}
Then hello_test.go
add a test:
func TestProverb(t *testing.T) {
want := "Concurrency is not parallelism."
if got := Proverb(); got != want {
t.Errorf("Proverb() = %q, want %q", got, want)
}
}
And then do it go test
to try:
$ go test
go: finding rsc.io/quote/v3 v3.1.0
go: downloading rsc.io/quote/v3 v3.1.0
go: extracting rsc.io/quote/v3 v3.1.0
PASS
ok example.com/hello 0.024s
$
Note now relied rsc.io/quote
and rsc.io/quote/v3
two module:
$ go list -m rsc.io/q...
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.1.0
$
Each different major versions of a module has a different guide package path: from the beginning v2, the guide path must end with a major package version. E.g. v3
version of rsc.io/quote
the guide path is the package rsc.io/quote/v3
. This habit is called semantic import versioning
, and it makes not compatible between different major versions of the dependent packages have different names. Therefore, rsc.io/quote
the v1.6.0
the v1.5.2
two versions of the multiplex rsc.io/quote
. (Previous examples, rsc.io/sampler v1.99.99
it should be backwards compatible rsc.io/sampler v1.3.0
, but the bug or other errors may result in this case.)
go command allows a build in each individual package conduction path contains at most one version, that is to say the presence of at most one version of each major version: a rsc.io/quote
, a rsc.io/quote/v2
, a rsc.io/quote/v3
and the like. This is the equivalent of telling module author of a clear rule: For a module is not permitted at the same time dependent rsc.io/quote v1.5.2
and rsc.io/quote v1.6.0
, but allows dependent on a number of different major versions, because of their different paths lead pack. This allows the user module can be an incremental upgrade to a new major version. In this example requires both rsc/quote/v3 v3.1.0
in quote.Concurrency
and need to continue to use rsc.io/quote v1.5.2
, the ability to relatively large projects in this incremental upgrade is especially important.
Upgrading to the new master version dependent
From now to complete rsc.io/quote
the rsc.io/quote/v3
upgrade, due to the major version changed, and we need to anticipate that some might have an incompatible API change, after reading the dependencies of the doc, you can see Hello
becomes HelloV3
:
$ go doc rsc.io/quote/v3
package quote // import "rsc.io/quote"
Package quote collects pithy sayings.
func Concurrency() string
func GlassV3() string
func GoV3() string
func HelloV3() string
func OptV3() string
$
(There is a missing import a known bug, shown in a v3
)
will now be hello.go
the quote.Hello()
upgrade to quoteV3.HelloV3()
:
package hello
import quoteV3 "rsc.io/quote/v3"
func Hello() string {
return quoteV3.HelloV3()
}
func Proverb() string {
return quoteV3.Concurrency()
}
Here there is no need to rename the import of:
package hello
import "rsc.io/quote/v3"
func Hello() string {
return quote.HelloV3()
}
func Proverb() string {
return quote.Concurrency()
}
Again run this test:
$ go test
PASS
ok example.com/hello 0.014s
Remove the dependency unused
Now all has been removed for rsc.io/quote
use, but also in go.mod
and executed go list -m all
can be seen:
$ go list -m all
example.com/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1
$ cat go.mod
module example.com/hello
go 1.12
require (
golang.org/x/text v0.3.0 // indirect
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.0.0
rsc.io/sampler v1.3.1 // indirect
)
$
Why is this so? Because like go build
or go test
when such build a single package can easily determine what is missing what needs to be added, but can not determine what can be safely removed. Only after checking all the packages module in the package and these are integrated in order to remove the dependency unused. Common build commands will not load this information, so it can not safely remove the dependency.
go mod tidy
Command can rely on to clean up unused:
$ go mod tidy
$ go list -m all
example.com/hello
golang.org/x/text v0.3.0
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1
$ cat go.mod
module example.com/hello
go 1.12
require (
golang.org/x/text v0.3.0 // indirect
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1 // indirect
)
$ go test
PASS
ok example.com/hello 0.020s
$
to sum up
GoModule go is dependent on management's future, moduel mode can be used in all supported versions go (go1.11 and go1.12).
This article describes the use GoModule the following workflow:
go mod init
Create a new module, while initializinggo.mod
build``go test
And other build commands will depend on demand, added to thego.mod
go list -m all
View the current dependence of modulego get
Dependent changes specified version (or add a new dependency)go mod tidy
Remove the dependency unused
We encourage developers to start using GoModule in development and add in the project go.mod
and go.sum
.