Z.S.K.'s Records

golang学习(go mod入门)

在go初期都是使用GOPATH的方法管理依赖,说实话确认难用, 大部分的golang项目都是使用第三包的包管理工具, 如vendor,也只用过vendor,好在官方推出了go module,在go v1.12后基本stable了,也支持vendor, 赶紧来学习一下.

GO111MODULE

GO111MODULE 有三个值:off, onauto(默认值)

  • GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。

  • GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查找。

  • ```
    GO111MODULE=auto

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28

    默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:

    - 当前目录在GOPATH/src之外且该目录包含go.mod文件
    - 当前文件在包含go.mod文件的目录下面。

    修改golang环境变量:

    `go env -w GO111MODULE="on"`

    当然也可以使用

    `export GO111MODULE="on"`

    这两种方式是临时的,只对改终端有效,**在go1.12版本之后会自动识别,如果在目录下存在go.mod就会使用module方式**, 这个还是比较人性化的.



    ### 使用

    go modules使用起来也是非常方便

    #### go mod init

    ```bash
    mkdir govars && cd govars
    go mod init govars #govars就是模块名, 当然官方推荐使用 aaa.bbb/xxx/yyy的形式
    #执行完成之后会在当前目录下生成go.mod及go.sum文件, go.sum是一个构建状态跟踪文件。它会记录当前module所有的顶层和间接依赖,以及这些依赖的校验和,从而提供一个可以100%复现的构建过程并对构建对象提供安全性的保证

cat go.mod

1
2
module govars 
go 1.13

最开始只有这两行,一个指定模块名,另一个就是go的版本, 一般情况下go.mod这个文件也不需要管理.

go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件.

比如, 我在main.go中import github.com/MatrixAI/Golang-Demo,那么这个文件就会自动地添加依赖:

cat go.mod

1
2
3
4
5
6
7
8
module govars

go 1.13

require (
github.com/MatrixAI/Golang-Demo v0.0.0-20200103072352-8d075351fdbd
github.com/pelletier/go-toml v1.6.0 // indirect indirect表示这个包是间接引用
)

可以通过 go get ./...让它查找依赖,并记录在go.mod文件中

go mod replace

当需要使用本地包时, 可以直接通过go mod edit或者直接编译go.mod文件, 来添加/替换本地的包

1
2
3
4
5
6
7
8
9
10
11
12
13
module github.com/learn-golang/golang-mod

require (
github.com/learn-golang/golang-mod/first v0.0.0
github.com/learn-golang/golang-mod/second v0.0.0
github.com/sirupsen/logrus v1.4.2 // indirect
)

// 使用replace进行替换
replace github.com/learn-golang/golang-mod/first => ./first
replace github.com/learn-golang/golang-mod/second => ./second

go 1.13

indirect表示是间接依赖, 指在当前module中没有直接import,而被当前module使用的第三方module引入的包,相对的顶层依赖就是在当前module中被直接import的包。如果二者规则发生冲突,那么顶层依赖的规则覆盖间接依赖。

在这里github.com/sirupsen/logrus被引入,但当前项目未直接import,所以是一个间接依赖,而github.com/learn-golang/golang-mod/first被直接引入和使用,所以它是一个顶层依赖

而我们的replace命令只能管理顶层依赖,对于间接引用是无法使用replace的,因此有时会出现在go.mod中使用了replace到本地包, 但还出现go build时仍然去网上下载的原因。

那么如果我把// indirect去掉了,那么不就变成顶层依赖了吗?答案当然是不行。不管是直接编辑还是go mod edit修改,我们为go.mod添加的信息都只是对go mod的一种提示而已,当运行go build或是go mod tidy时golang会自动更新go.mod导致某些修改无效,简单来说一个包是顶层依赖还是间接依赖,取决于它在本module中是否被直接import,而不是在go.mod文件中是否包含// indirect注释

go mod tidy

go mod tidy主要是用于为go.mod增加丢失的依赖,删除不需要的依赖等.

go list

显示所有Import库信息

go list -m all

1
2
3
4
5
6
7
govars
github.com/BurntSushi/toml v0.3.1
github.com/MatrixAI/Golang-Demo v0.0.0-20200103072352-8d075351fdbd
github.com/davecgh/go-spew v1.1.1
github.com/pelletier/go-toml v1.6.0
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
gopkg.in/yaml.v2 v2.2.4

也可查看json详细格式 go list -m all -json

当然还有一些其它的操作, 以后用到了再深入, 从上手的效果来看,确实比GOPATH、vendor省事, 很多事要可以交给go module去做了.

参考文章:

转载请注明原作者: 周淑科(https://izsk.me)

 wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?