Use GoModule (Using Go Modules translation)

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.modset of GoPackage file, go.modfile 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 versionthe form as a module pathwrite go.mod.

In Go1.11 when, in $GOPATH/srca file or folder other than any parent path contains go.moda file, it can be used in GoModule go command. (For compatibility, $GOPATH/srcthe files in the folder even if there is go.moda 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/srcaddition 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.modfile, 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 $GOPATHcase 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 initto enable module mode and the current path made of the root path module, and then execute go testfacie 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 initthe command generates a go.modfile:

$ cat go.mod
module example.com/hello

go 1.12
$

go.modThe file will only appear in the root directory module, subdirectory import pathby the module pathrelative 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/hellopart 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.moddependent and versions listed in the file, if found go.modnot 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 testresolve to the new import-- rsc.io/quotelatest version is v1.5.2, and it used two dependent - rsc.io/samplerand golang.org/x/textonly 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.modthe case of up-to-date execution again go testwill not be repeated this operation, the module will be downloaded to the cache $GOPATH/pkg/modin.

Although the go command attention convenient, but this does not mean the end. Now module strictly dependent on go.modthe specified name in the given version.

As described above, adding a direct dependency usually lead to other indirect dependency, execution go list -m allcan 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 moduleis always appears on the first line, is then sorted by the path module dependencies.

Dependencies golang.org/x/textversion v0.0.0-20170915032832-14c0d48ead0cis pseudo-versiona, this is the version without a tag syntax for the situation.

Also go.sumit is used as go.moda 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.sumto 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.modAnd go.sumit 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 allcan see the output, currently in use golang.gor/x/textit 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 allas 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/texthas been upgraded to the newest tag version (v0.3.0), and go.modalso updated simultaneously. Here's indirectcomment indicates that this was not dependent on the current module directly, only being dependent on other dependencies. You can go help modulessee the details.

We will now rsc.io/samplerlook to upgrade minor version, the same execution go getand 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/sampleris 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 getcommand @v1.3.1display parameters, usually all go getparameters can be displayed with a version number, default to @latestrepresent the latest version.

Adding new master version dependencies

Now in the care of a wash added func: func Proverbto return a concurrent go proverb, by calling rsc.io/quote/v3in quote.Concurrencyto achieve. First, hello.goadd 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.goadd 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 testto 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/quoteand rsc.io/quote/v3two 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. v3version of rsc.io/quotethe 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/quotethe v1.6.0the v1.5.2two versions of the multiplex rsc.io/quote. (Previous examples, rsc.io/sampler v1.99.99it 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/v3and 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.2and 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.0in quote.Concurrencyand 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/quotethe rsc.io/quote/v3upgrade, 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 Hellobecomes 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.gothe 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/quoteuse, but also in go.modand executed go list -m allcan 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 buildor go testwhen 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 tidyCommand 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 initCreate a new module, while initializinggo.mod
  • build``go testAnd other build commands will depend on demand, added to thego.mod
  • go list -m allView the current dependence of module
  • go getDependent changes specified version (or add a new dependency)
  • go mod tidyRemove the dependency unused

We encourage developers to start using GoModule in development and add in the project go.modand go.sum.

Published 69 original articles · won praise 55 · views 190 000 +

Guess you like

Origin blog.csdn.net/xmh19936688/article/details/104993226