美文网首页
Go Module碎碎念

Go Module碎碎念

作者: 小餐包 | 来源:发表于2021-10-17 17:26 被阅读0次

    本文主要参考文章,个人整理而成。

    Go Modules是官方正式推出的包依赖管理项目,在Go Modules推出之前(Go1.13之前)存在两个蛋疼问题:

    • 当你使用go get命令安装依赖包时,这些包文件总是保存到 $GOPATH/src 目录下。Go程序只能导入$GOPATH/src目录下的依赖包,这种设定强制要求所有的go的项目目录必须在$GOPATH/src目录下设定导致:如果你的项目在别的目录,那么你将需要频繁切换GOPATH的值,而整个$GOPATH目录非常臃肿;
    • 另一个问题是,由于go get总是将这些依赖文件放到相同的目录下(因为目录名与包名相同),导致一个依赖包的多个版本无法共存,这就导致非常容易出现不兼容的问题。而如果你想在别的路径下工作,除了切换GOPATH的值外,所有的依赖需要重新安装。

    Go modules 出现的目的之一就是为了解决 GOPATH 的问题,也就相当于是抛弃 GOPATH 了。它有如下特点:

    • 以前项目必须在$GOPATH/src 里进行,现在Go 允许在$GOPATH/src外的任何目录下使用 go.mod 创建项目。

    • 在依赖包版本控制方面,引入了语义化版本的概念,即按照vX.Y.Z的格式定义版本,其中X为主版本,Y为小版本,Z为补丁版本。Go假定当一个依赖包存在不兼容的Breaking changes时,它的主版本将会变化,Go会将不同主版本的依赖包视为不同的module,因此两个不同主版本的依赖包同时存在是非常普遍的。如果是小版本变化(主版本号不变),那这个模块版本肯定就不包含 Breaking changes,这时如果两个依赖包A和B都依赖另一个不同小版本的依赖包C的话,那么就安装最新的依赖包C就行了。

    • 当我们希望发布依赖包公用时,你需要提供一个commit hash或者使用一个类似于git tag的方式为这个commit hash添加一个别名。这些Tag必须遵循语义化版本控制,如果没有将忽略 Tag,然后根据你的 Commit 时间和哈希值再为你生成一个假定的符合语义化版本控制的版本号。

    • Global Caching 这个主要是针对 Go modules 的全局缓存数据说明,如下:

      • 同一个模块版本的数据只缓存一份,所有其他模块共享使用。
      • 目前所有模块版本数据均缓存在 $GOPATH/pkg/mod$GOPATH/pkg/sum 下,未来或将移至 $GOCACHE/mod$GOCACHE/sum 下( 可能会在当 $GOPATH 被淘汰后)。
      • 可以使用 go clean -modcache 清理所有已缓存的模块版本数据。
    • 新增了 go env -w 用于写入环境变量,而写入的地方是 os.UserConfigDir 所返回的路径,需要注意的是 go env -w 不会覆写系统环境变量,类似于git config的作用。

    go.mod文件

    go.mod 是启用了 Go moduels 的项目所必须的最重要的文件,它描述了当前项目(也就是当前模块)的元信息,每一行都以一个动词开头,目前有以下 5 个动词:

    • module:用于定义当前项目的模块路径。
    • go:用于设置预期的 Go 版本。
    • require:用于设置一个特定的模块版本。
    • exclude:用于从使用中排除一个特定的模块版本。
    • // indirect:表名该模组并不是我们程序中直接依赖的,而是直接依赖的包里面导入的依赖;
    • replace:用于将一个模块版本替换为另外一个模块版本,比如用local的版本替代remote的版本。

    go.sum文件

    go.sum类似于npm中的package-lock.json 这类文件,它详细罗列了当前项目直接或间接依赖的所有模块版本,并写明了那些模块版本的 SHA-256 哈希值以备 Go在今后的操作中保证项目所依赖的那些模块版本不会被篡改。但是必须注意的是,不同于其他语言,go.sum文件更新应该包含在你的提交中,以确保你的依赖模块可以100%被重新构建。

    GOPROXY配置

    这个环境变量主要是用于设置 Go 模块代理,它的值是一个以英文逗号 “,” 分割的 Go module proxy 列表,默认是proxy.golang.org,国内访问不了。这里要感谢盛傲飞和七牛云为中国乃至全世界的 Go 语言开发者提供免费、可靠的、持续在线的且经过CDN加速Go module proxy(goproxy.cn)。

    其实值列表中的 “direct” 为特殊指示符,用于指示 Go 回源到模块版本的源地址去抓取(比如 GitHub 等),当值列表中上一个 Go module proxy 返回 404 或 410 错误时,Go 自动尝试列表中的下一个,遇见 “direct” 时回源,遇见 EOF 时终止并抛出类似 “invalid version: unknown revision...” 的错误。

    国内推荐配置为:

    export GOPROXY="https://goproxy.cn, direct"
    # 或者
    go env -w GOPROXY=https://goproxy.cn,direct
    

    Vendor目录

    有时由于一些网络原因我们可能无法下载我们需要的依赖,这时我们需要提前准备这些依赖。我们可以通过go mod vendor 命令输出我们所有的依赖到对应的 vendor 目录(位于我们自己的模组目录下),然后通过运行go build -mod vendor命令来强制使用vendor目录的依赖。

    命令汇总

    # 查看所有 go mod的使用命令
    go mod
    # module为项目目录名,生成 go.mod 文件
    go mod init [module-name]
    # 更新现有依赖
    go mod tidy
    # 下载 go.mod 文件中指明的所有依赖
    go mod download 
    # 查看项目所有依赖
    go list -m all
    # 查看现有的依赖结构
    go mod graph
    #  编辑 go.mod 文件
    go mod edit
    # 导出现有的所有依赖 (事实上 Go modules 正在淡化 Vendor 的概念)
    go mod vendor
    # 校验一个模块是否被篡改过
    go mod verify
    # 清理所有已缓存的模块版本数据。
    go clean -modcache
    # 更新主要模块,但是忽略单元测试
    go get -u
    # 更新所有模块,推荐使用
    go get -u all
    

    相关文章

      网友评论

          本文标题:Go Module碎碎念

          本文链接:https://www.haomeiwen.com/subject/mcewoltx.html