浅谈GO语言包管理

本文介绍了Go语言的包管理,包括GOPATH模式和GOMODULE模式的演变,重点讲解了GOMODULE模式的使用,如如何启用、初始化及管理依赖。此外,还解析了go.mod和go.sum文件的作用,go.mod用于定义模块和依赖,go.sum用于验证模块内容的校验和。最后,强调了gomod命令的常用操作及其在项目管理中的重要性。
摘要由CSDN通过智能技术生成

一、包管理的作用

不论是哪种语言,都会有很多大佬写的框架以及工具包,我们为了可以增加代码跨项目的可复用性,经常会把一些常用的功能或者轮子写成一个或者多个包,因为包的独立性,使得我们可以在不同的项目或仓库对它进行使用,间接提高了代码的可复用性,减少了 CP 的场景。

不同语言对包的概念界限不同,但是他们的本质是相同的,都是为了提供一些便于开发使用的工具方法或者轮子。本质就是一个文件夹的代码,当然包可以用来区分相同名字的函数、变量等标识符等。

二、如何进行包管理

1. GOPATH 模式

Go 的包管理方式是逐渐演进的, 最初是所有的包都放在 GOPATH 里面,使用类似命名空间的包路径区分包,不过这种包管理显然是有问题,由于包依赖可能会引入破坏性更新,这种模式下,代码如果不在GOPATH下就无法进行编译。

2. GO MODULE 模式

As of Go 1.11, the go command enables the use of modules when the current directory or any parent directory has a go.mod, provided the directory is outside $GOPATH/src. (Inside $GOPATH/src, for compatibility, the go command still runs in the old GOPATH mode, even if a go.mod is found. See the go command documentation for details.) Starting in Go 1.13, module mode will be the default for all development.

从Go 1.11开始,Go命令允许在当前目录或任何父目录运行时使用模块。如果目录在 G O P A T H / s r c 之 外 。 ( 在 GOPATH/src之外。(在 GOPATH/src(GOPATH/src中,为了兼容,go命令仍然运行在旧的GOPATH模式下,即使找到了 go.mod 文件。详情请参阅go命令文档。)从Go 1.13开始,module 模式将是所有开发的默认模式。

这就意味着,官方建议所有人都使用 go module 模式进行包管理。

基于这种模式,我们将摆脱 go project 必须写在 gopath 下的噩梦,而是随处可以创建项目。

3.如何使用 go module

目前 gomod 在 Go v1.12 功能基本稳定,到本 v1.13 将默认开启。

既然是新的管理模式,必然是有开关类的参数。

3.1 开启 Go module
  • 1.11和1.12版本
    将下面两个设置添加到系统的环境变量中
GO111MODULE=on
GOPROXY=https://goproxy.io
  • 1.13版本之后
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
  • GO111MODULE=off 无模块支持,go 会从 GOPATH 和 vendor 文件夹寻找包。
  • GO111MODULE=on 模块支持,go 会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod 下载依赖。
  • GO111MODULE=auto 在 $GOPATH/src 外面且根目录有 go.mod 文件时,开启模块支持。
3.2 使用 go module

Usage:

    go mod <command> [arguments]

The commands are:

    download    download modules to local cache
    edit        edit go.mod from tools or scripts
    graph       print module requirement graph
    init        initialize new module in current directory
    tidy        add missing and remove unused modules
    vendor      make vendored copy of dependencies
    verify      verify dependencies have expected content
    why         explain why packages or modules are needed

命令怎么使用,当然最好的方式就是看文档说明了。毕竟一手资料才是最靠谱的。在日常的使用中,其实最常用的也就这几个命令。

  • 初始化 go mod
go mod init xxx 
  • 依赖包会自动下载到$GOPATH/pkg/mod,多个项目可以共享缓存的mod
go mod download
  • 从mod中拷贝到项目的vendor目录下,这样IDE才可以识别
go mod vendor
  • 补充丢失的模块或者删除没有使用的模块
go mod tidy

三、探讨 go.mod 和 go.sum

1. go.mod

当你在源码根目录执行了

go mod init xxx 

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

go.mod 提供了module, require、replace和exclude 四个命令

  • module 语句指定包的名字(路径)
  • require 语句指定的依赖项模块
  • replace 语句可以替换依赖项模块
  • exclude 语句可以忽略依赖项模块

当你有 import 一些其他的依赖包的,也会同时生成 go.sum 文件,例如以下代码:

package main

import (
	"fmt"
	"github.com/astaxie/goredis"
)
func main()  {
	var client goredis.Client
	client.Addr = "127.0.0.1:6379"

	_ = client.Set("a", []byte("hello"))
	val, _ := client.Get("a")

	fmt.Println(string(val))
}

其中目录结构如下:

.
├── go.mod
├── go.sum
└── main
    └── main.go

此时我们打开一下 go.mod ,看看里面是什么东西。

~/study/GO/go-test/src  cat go.mod
module mclink-test

go 1.14

require github.com/astaxie/goredis v0.0.0-20160824151742-1f1c6e6fc3a8

对其我们简单解释一下,第一个是模块的名称,也就是你执行 go mod init xxx 的这个 xxx

然后是 go 的版本,再然后就是以来的包路径及对应的版本。

在执行命令go mod tidy时,Go module 会自动整理go.mod 文件,如果有必要会在部分依赖包的后面增加// indirect注释。一般而言,被添加注释的包肯定是间接依赖的包,而没有添加// indirect注释的包则是直接依赖的包,即明确的出现在某个import语句中。

比如说你使用的包里面也用了别人的包,这时候别人的包就属于间接依赖,会在后面加上 // indirect 的注释

当我们希望确定间接依赖github.com/Rican7/retry v0.1.0 // indirect是被哪个依赖引入的,则可以使用命令go mod why来查看,例如:

$ go mod why -m golang.org/x/net
# golang.org/x/net
main/main
google.golang.org/grpc
golang.org/x/net/trace

另外,命令go mod why -m all则可以分析所有依赖的依赖链

2. go.sum

从其他语言过来的大佬可能一开始会以为 go.sum 是用来锁版本的,其实并不是,它的作用和 PHP composer 下的 composer.lock 完全不是一个概念。

Is ‘go.sum’ a lock file? Why does ‘go.sum’ include information for module versions I am no longer using?
No, go.sum is not a lock file. The go.mod files in a build provide enough information for 100% reproducible builds.

For validation purposes, go.sum contains the expected cryptographic checksums of the content of specific module versions. See the FAQ below for more details on go.sum (including why you typically should check in go.sum) as well as the “Module downloading and verification” section in the tip documentation.

In part because go.sum is not a lock file, it retains cryptographic checksums for module versions even after you stop using a module or particular module version. This allows validation of the checksums if you later resume using something, which provides additional safety.

In addition, your module’s go.sum records checksums for all direct and indirect dependencies used in a build (and hence your go.sum will frequently have more modules listed than your go.mod).

go.sum不是锁定文件。go.mod构建中的文件为100%可复制的构建提供了足够的信息。出于验证目的,go.sum包含特定模块版本的内容的预期密码校验和。有关详细信息(包括为什么通常需要签入)以及技巧文档中的“模块下载和验证”部分,请参见下面的常见问题解答。
由于go.sum不是锁文件,因此即使您停止使用模块或特定模块版本,它也会保留模块版本的加密校验和。如果您以后继续使用某些内容,则可以验证校验和,从而提供了额外的安全性。另外,您的模块go.sum记录了构建中使用的所有直接和间接依赖项的校验和(因此,go.sum列出的模块通常比的要多go.mod)。

go.sum 的每一行都是一个条目,大致是这样的格式:

<module> <version>/go.mod <hash>
<module> <version> <hash>
<module> <version>/go.mod <hash>

其中module是依赖的路径,version是依赖的版本号。hash是以h1:开头的字符串,表示生成checksum的算法是第一版的hash算法(sha256)。

例如:

$ cat go.sum
github.com/astaxie/goredis v0.0.0-20160824151742-1f1c6e6fc3a8 h1:XN8UQV0Zro09FeYjkwEdGTmP+QFXfc95EDXKRxhOUAs=
github.com/astaxie/goredis v0.0.0-20160824151742-1f1c6e6fc3a8/go.mod h1:i0oI4E/DxCwoJG6iblWnjgLaTrbSEOtUxLtcZA6i7ac=

其中版本的规则相对比较复杂,但是可以归为几类说明。
在这里插入图片描述

四、小总结:

go mod 最大的好处就是可以在任意位置创建 go 项目,目前官方已强烈建议开发者使用 go mod 进行包依赖的管理。并且我们应该将 go.mod & go.sum 文件纳入 VCS 中。了解包管理工具,是每个开发者必须要经历的过程。本文用较小篇幅讲述了 go mod 的一些基本内容,如果想要进一步了解,点击查询官方文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MClink

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值