如果你还在使用 GOPATH 模式来开发Golang程序,那么你可以参考本文来告别 GOPATH,并带给你一个方便的包管理工具。

环境准备

走通流程

1.新建文件夹demo加入gopath,然后在demo中新建src文件夹并在src下新建test文件夹,D:\demo\src\test
2.cmd进入D:\demo\src\test,执行go mod init ,初始化,会生成一个go.mod文件
3.导入你需要的包,go mod vendor,会生成vendor文件夹,里面就是该项目目前需要的依赖
image.pngimage.png
4.如果依赖包需要更新或修改,直接修改go.mod即可
5.当需要新增包时,你只需要import 再 go mod vendor即可,它会帮你扫描整个项目文件
注意:goland的moudle下,不会引入vendor下的包,使用go mod tidy拉包
image.png

常见问题

  1. go mod init 时报错

go: cannot determine module path for source directory D:\test\src\111 (outside GOPATH, no import comments):这是因为你没在GOPATH下进行操作,不能直接用go mod init ,而要在init 后加上你的项目名
例如:项目目录:aaa/bbb/ccc ,首先进入aaa/bbb/ccc,然后 go mod init ccc 就会在ccc下生成mod文件

  1. 没用vendor虚拟环境,导包报红但不影响运行的情况

图片.png

命令

命令 说明
download 下载依赖包到本地的CACHE
edit 编辑go.mod
graph 打印模块依赖图
init [项目名] 初始化mod,如果不在gopath下,项目名必须加,否则报错
tidy 拉取缺少的模块,移除不用的模块
vendor 新建vendor目录,将所有依赖全部拉进来
verify 验证依赖是否正确
why 解释为什么需要依赖
go build -mod=vendor 忽略cache中的包,使用vendor目录的依赖进行编译

indirect

在使用 Go module 过程中,随着引入的依赖增多,也许你会发现go.mod文件中部分依赖包后面会出现一个// indirect的标识。这个标识总是出现在require指令中,其中// 与代码的行注释一样表示注释的开始,indirect表示间接的依赖

在执行命令go mod tidy时,Go module 会自动整理go.mod 文件,如果有必要会在部分依赖包的后面增加// indirect注释。一般而言,被添加注释的包肯定是间接依赖的包,而没有添加// indirect注释的包则是直接依赖的包,即明确的出现在某个import语句中。
然而,这里需要着重强调的是:并不是所有的间接依赖都会出现在 go.mod文件中。
间接依赖出现在go.mod文件的情况,可能符合下面所列场景的一种或多种:

  • 直接依赖未启用 Go module

    1. require (
    2. B vx.x.x
    3. B1 vx.x.x // indirect
    4. B2 vx.x.x // indirect
    5. )

    go mod - 图5

  • 直接依赖go.mod 文件中缺失部分依赖

    1. require (
    2. B vx.x.x
    3. B2 vx.x.x // indirect
    4. )

    go mod - 图6

incompatible

以Module github.com/RainbowMango/m 为例,假如其当前版本为v3.6.0,因为其Module名字未遵循Golang所推荐的风格,即Module名中附带版本信息,我们称这个Module为不规范的Module。
不规范的Module还是可以引用的,但跟引用规范的Module略有差别。
如果我们在项目A中引用了该module,使用命令go mod tidy,go 命令会自动查找Module m的最新版本,即v3.6.0。 由于Module为不规范的Module,为了加以区分,go 命令会在go.mod中增加+incompatible 标识

  1. require (
  2. github.com/RainbowMango/m v3.6.0+incompatible
  3. )

除了增加+incompatible(不兼容)标识外,在其使用上没有区别。

命名规范

Module的版本号需要遵循v<major>.<minor>.<patch>的格式,此外,如果major版本号大于1时,其版本号还需要体现在Module名字中。
比如Module github.com/RainbowMango/m,如果其版本号增长到v2.x.x时,其Module名字也需要相应的改变为: github.com/RainbowMango/m/v2

实例

replace:

image.png

注意:也可以使用提交的hash

  1. 例如:
  2. replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 b51e752
  3. 执行 go mod tidy 后自动变成
  4. replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.1.0

不同项目之间的引用:

image.png

采坑记

ambiguous import

image.png
解决

  1. 将一个替换为另外一个,如:
  2. replace google.golang.org/grpc v1.31.1 => google.golang.org/grpc/examples v0.0.0-20200826230536-d31b6710005d

但是replace google.golang.org/grpc v1.31.1我本身就做了replace
image.png
会出现如下的错误
image.png
正确的应该是

  1. replace google.golang.org/grpc v1.31.1 => google.golang.org/grpc v1.27.0
  2. replace google.golang.org/grpc v1.27.0 => google.golang.org/grpc/examples v0.0.0-20200826230536-d31b6710005d

这时这个问题又出现了….
image.png
检查mod文件
image.png

发现require中这个包已经被间接引用,删除require里重复的这个即可

按上面解决后可能会出现 used for two different module paths
image.png
检查go.mod文件,发现需要替换的,在require中且是被间接引用,我们把require中框红的这个删除即可
image.png

go mod拉取私有项目

比如我的项目是https://github/ABDC/logs
设置环境变量,重启IDE

  1. GOPRIVATE=github.com/ABCD

TOKEN

如果还有权限问题,win下的操作如下,在.gitconfig 新增
从你gitlab平台生成一个token

  1. [http]
  2. extraheader = PRIVATE-TOKEN: 你的token
  3. [url]
  4. insteadOf = https://gitlab.你的gitlab服务器.com

image.png
对本项目生效:

  1. git config http.extraheader "PRIVATE-TOKEN:YOUR_PRIVATE_TOKEN"

对所有git项目生效:

  1. git config --global http.extraheader "PRIVATE-TOKEN:YOUR_PRIVATE_TOKEN"

SSH Key

1.打开本地git bash,使用如下命令生成ssh公钥和私钥对
ssh-keygen -t rsa -C 'xxx@xxx.com' 然后一路回车(-C 参数是你的邮箱地址)

2.然后打开~/.ssh/id_rsa.pub文件(~表示用户目录,比如我的windows就是C:\Users\Administrator),复制其中的内容

3.打开gitlab,找到Profile Settings—>SSH Keys—->Add SSH Key,并把上一步中复制的内容粘贴到Key所对应的文本框,在Title对应的文本框中给这个sshkey设置一个名字,点击Add key按钮
image.png
4. 到此就完成了gitlab配置ssh key的所有步骤,我们就可以愉快的使用ssh协议进行代码的拉取以及提交等操作了

  1. 再试一下拉取代码和提交代码,应该就不需要输入密码了

本地配置多个ssh key

大多数时候,我们的机器上会有很多的git host,比如公司gitlab、github、oschina等,那我们就需要在本地配置多个ssh key,使得不同的host能使用不同的ssh key ,做法如下(以公司gitlab和github为例):

  1. 为公司生成一对秘钥ssh key
  2. ssh-keygen -t rsa -C 'yourEmail@xx.com' -f ~/.ssh/gitlab-rsa
  3. github生成一对秘钥ssh key
  4. ssh-keygen -t rsa -C 'yourEmail2@xx.com' -f ~/.ssh/github-rsa

在~/.ssh目录下新建名称为config的文件(无后缀名)。用于配置多个不同的host使用不同的ssh key,内容如下:

  1. # gitlab
  2. Host gitlab.com
  3. HostName gitlab.com
  4. PreferredAuthentications publickey
  5. IdentityFile ~/.ssh/gitlab_id-rsa
  6. # github
  7. Host github.com
  8. HostName github.com
  9. PreferredAuthentications publickey
  10. IdentityFile ~/.ssh/github_id-rsa
  11. # 配置文件参数
  12. # Host : Host可以看作是一个你要识别的模式,对识别的模式,进行配置对应的的主机名和ssh文件
  13. # HostName : 要登录主机的主机名
  14. # User : 登录名
  15. # IdentityFile : 指明上面User对应的identityFile路径

按照上面的步骤分别往gitlab和github上添加生成的公钥gitlab_id-rsa.pub和github_id-rsa.pub
OK,大功告成,再次执行git命令验证是不是已经不需要再次验证权限了。

go get 拉取私有项目

~/.netrc 中按照下面的写法添加你的 GitLab 账号和密码。这些内容在安装内部的私有包时需要用到。如果不存在这个文件就创建它

  1. machine xxx.com
  2. login your_name
  3. password your_password