舍近求远,为什么 Golang 要这样读取本地的 package?
我们知道,Python 的第三方库一般是托管到 Pypi 上面的,使用 pip
命令进行安装。而 Golang 很多第三方库是托管在 Github 上面的,使用 go get
进行安装。
有时候,我们会发现一个很奇怪的现象,很多 Golang 的项目,在引用自己项目里面的包的时候,竟然用的是 Github 上面的地址。
例如我们看这个项目:https://github.com/kingname/handsome ,它的入口文件是main.go
。我们打开这个文件,会看到里面import
语句中,从 Github导入自身的util
包:
可问题是,这个 util
文件夹就在main.go
旁边啊:
如果是在 Python 里面,入口文件main.py
旁边有一个util
文件夹,这个文件夹里面有一个util.py
的文件,那么我们直接写from util.util import xxx
就可以导入util.py
文件中的函数了。为什么 Golang 里面要从 Github 导入?那如果我更新了util/util.go
文件里面的内容,但是我没有把这次修改上传到 Github 中,当我运行go run main.go
的时候,运行的是老代码还是新代码?用的是我本地的版本还是 Github 上面的版本?
这个问题的关键,就在go.mod
这个文件中。打开请看这个文件的第一行:
可以看到,这个项目是使用 go mod
进行管理的,并且指定这个模块的名字,就叫做github.com/kingname/handsome
。
所以,当我们执行命令go run main.go
的时候,Golang 的编译器知道自己就是github.com/kingname/handsome
,那么main.go
里面导入github.com/kingname/handsome/util
,实际上就是本项目自身根目录的 util
文件夹中的包,它不会发起网络请求,不会从 Github 上面重新下载。每次运行的时候,使用的总是项目util/util.go
中的内容。
但是,如果你现在在另外一个项目里面导入github.com/kingname/handsome/util
,Golang 从go.mod
中知道当前运行的项目跟即将导入的这个包不在同一个项目中,于是它就会去 Github 上面拉代码下来运行。
这个规则,可以在 Golang 的官方文档Module paths这一节找到:Go Modules Reference - The Go Programming Language。