go mod镜像加速

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

清除缓存

  1. 清除所有的包缓存
go clean --modcache
  1. 清除特定版本的包缓存(暂时没发现)

目录结构

目录为go/pkg/mod
├── cache
├── dubbo.apache.org
├── github.com
├── gitlab.dian.org.cn
├── git.sublive.app
├── go.etcd.io
├── golang.org
├── google.golang.org
├── gopkg.in
├── gorm.io
├── go.uber.org
└── vimagination.zapto.org
cache记录压缩包和校验文件等内容
不同的网站拥有不同的文件夹存放

包与路径

  1. import的是包的路径,不是包名,会根据import的值去寻找这个路径下的包
  2. import之后会去路径下找包,找到文件中第一行声明的package才是真正的包名
  3. 路径下的包名可以和目录不一样(最好一样),但是同一个路径只能有一个包名

私有仓库包获取

  1. go env -w GOPRIVATE="*.gitlab.cn" 设置为私有仓库
  2. go env -w GONOPROXY="*.gitlab.cn" 设置不走代理
  3. 编辑~/.netrc文件(这个文件是纯文本文件不能使用任何的环境变量)
machine git.gitlab.cn login chenxuan password 123456789
  1. 第三步也可以更改为编辑~/.gitconfig文件
[url "ssh://git@github.com/"]
	insteadOf = https://github.com/
  1. git config --global http.sslverify false 解除git ssl验证

某个pkg最新版本

  1. 更改go.mod中的包版本为v0.0.0

gitlab不支持ssh拉取多级私有包

问题原因

  • go get分两个过程,可以使用go get -v查看记录
    • 获取链接的源信息,即meta data,此时使用的是https协议
    • 下载代码,此时使用的是ssh(当然这里也可以更改为http)
  • 超过2的sub目录在 未认证的情况下因为可能是仓库的信息(也可能是sub目录,一级不可能是仓库),这里涉及仓库信息,因此https没带这token禁止获取
  • 使得go get命令无法获取超过1 的仓库的meta data,无法clone

解决办法

netrc

replace

require (
	private.gitlab.instance/project/team/somename v1.0.0
)

replace (
	private.gitlab.instance/project/team/somename => private.gitlab.instance/project/team/somename.git v1.0.0
)
  • 添加.git后缀,这个办法也可以改进为直接包名带着.git
  • 优点:能解决问题,而且没有信息泄漏问题,简单方便
  • 缺点:丑陋,莫名其妙带上.git

相关讨论连接

  • https://github.com/golang/go/issues/34094#issuecomment-556898897
  • https://gitlab.com/gitlab-org/gitlab/-/issues/36354

go多级包管理

  • go mod init github.com/{帐号}/{仓库名字}/{子包的名字},目录demo
.
├── README.md
├── a
│   ├── a.go
│   └── go.mod
└── b
    ├── b.go
    └── go.mod
  • 需要注意的是,这时候的tag规则是{子包的相对路径}/v1.0.0
git tag
a/v1.0.0
b/v1.0.0
b/v1.0.1
  • import的时候是tag需要注意
import (
	github.com/robberphex/go-test-multi-module/a v1.0.0
)
  • 参考:https://learnku.com/articles/58947 和 https://tonybai.com/2023/05/10/a-guide-of-managing-multiple-go-modules-in-mono-repo/

引用特定分支

  1. 直接使用 go get 命令 类似 go get github.com/golang/go@master
  2. 直接在go.mod文件中添加,格式: git地址 v0.0.0-时间戳- commint id 例如: github.com/golang/go v0.0.0-20221013081251-69aaa89ae530

依赖地狱

  • 项目引用了 A包和B包, A和B都引用了C包, 但是A用的是v1.0,B用的是v2.0, C包的v2.0不兼容 v1.0 , 导致崩溃无法编译
  • go mod的解决办法是通过package路径加上version使得两个包依赖的完全是不同的的包, 使得同一个程序可以存在两个相同名字版本不同的包(本质依赖了包本身是隔离的,不会引起冲突的问题)
    • 第一个代价就是构建出来的app的二进制文件size变大了,因为二进制文件中包含了多个版本的P3的代码;第二个代价,可能也算不上代价,更多是要注意的是不同版本的module之间的类型、变量、标识符不能混用
  • 需要注意的是: 这种的多版本共存的情况只存在于, 两个package version的 major 版本发生了不同, 如果是同一个major, 那么会使用最大的版本号(可能出现不兼容问题)

[!tip] 参考 为什么有了Go module后“依赖地狱”问题依然存在 | Tony Bai