Go 包管理
Package
go 的文件都以 package PACKAGE_NAME
开头,表示这个文件属于哪个包,如果是 package main
表示这个文件是可以运行的。同一目录下的文件的package名称都相同。
我们可以通过新建一个目录,在目录下新建若干 go 源文件的方式来创建自己的 package,每个 go 源文件的的 package 的名字都是统一的(即我们创建的包的名字),它们也都属于同一个包,不同源文件中定义的函数也都可以互相使用,并不存在需要先声明再调用的限制。在该目录下可以使用 go build
对我们的包进行编译。
在其他文件中,可以使用 import "path/to/PACKAGE_NAME"
来导入包,从而引用包中的结构体、函数等等。go 不允许循环引用。使用 import ALIAS "path/to/PACKAGE_NAME"
的方式可以以别名的形式导入包。
go 也不允许导入未使用的包,如果我们需要使用某个包中的 init() 方法,但又不会使用这个包,可以使用import _ PACKAGE
匿名导入。如果导入了未使用的包,编译会报错,一个比较好的方式是使用goimports
工具,可以自动清除文件中未使用的导入包。对某个路径下的所有文件使用goimports
的方法为:goimports -w path/
在package中,我们可以定义一系列的变量、常量、类型、结构体、方法、函数等,如果我们定义的变量、函数、etc…的名称是大写开头,则这些变量、函数对于调用这个包的外部调用者是可见的,如果是小写开头,则这些变量、函数就叫做unexported(未导出的),可以理解为私有方法,只有在包的内部才能使用这些变量、函数。这样的方式提供了安全性和更好的封装性,包的调用者不需要关心一些实现细节,而是只使用包提供的方法。
有些包中可能会需要一个初始化函数,来初始化一些全局变量,比如初始化某个map的长度,初始化一个数据库链接等等。在包中使用init()
函数,则在初始化的时候,init()
中的内容会自动执行。每个包都会以导入的顺序进行初始化,然后 main 函数才会开始执行。
另一种初始化包级变量的方式是手动定义可导出的初始化函数,比如InitMap()
,然后在主函数的文件的init()
函数中,手动调用这个包的InitMap()
Go Module
go提供了自己的包管理工具 go mod
,在环境变量中配置export GO111MODULE=on
即可使用。go mod
可以自动添加、删除、下载依赖,支持从常用的git仓库如GitHub下载依赖,非常易于使用。
在项目中使用 go mod init
,会初始化一个go.mod
文件,里面记录了项目文件中依赖的包以及对应版本。使用go mod tidy
,则会自动整理(添加、删除)依赖,包括下载依赖包,但不会更新依赖包在 go.mod
中记录的版本。想要将某个依赖更新到最新版,可以使用go get XXX
。关于go get
有几点冷知识:
go get XXX
某个包,如果这个包之前是用语义化版本控制的,也就是git上打tag的v1.0.4
的这种形式,那么go get
只会更新这个包到最新的语义化版本,也就是说如果有最新的commit没有打tag,使用go get
还是不能更新到这个commit,这时可以用get get XXX@master
go get -u XXX
中的-u
参数不是更新到最新版本的意思,而是指同时更新该依赖中所有参与编译的依赖到最新版本- 若
go get
的目标package为main,还会同时编译安装二进制到$GOPATH/bin
如果多个依赖包中对某个特定依赖包的依赖版本不同,go mod
会选择所有依赖版本中最高的那个版本
如果想要强制指定某个依赖的版本,比如因为兼容性问题不想更新到最新版的时候,则可以在go.mod
中使用replace
,比如:
replace github.com/golang/protobuf => github.com/golang/protobuf v1.3.5
使用go mod graph
可以查看所有依赖项之间的依赖关系,比如用go mod graph | grep XXX
可以查到某个依赖项是如何被依赖的。
常见报错:
- 升级了某个依赖之后,编译报错。原因一般是使用了
go get -u
同时升级了依赖的依赖,而导致了不兼容,所以如无必要,不使用-u
参数 unknown revision v1.X.X
:该依赖包的远程的某个版本被删掉了,这时编译时就会因为找不到对应版本而报错,解决方法是将依赖更新到最新版本
以上是 Go 包管理 的全部内容, 来源链接: utcz.com/z/264381.html