文章目录
- 包与工程化
- 用go mod管理工程
- 包引入规则
- init调用链
- 可见性
包与工程化
用go mod管理工程
初始化项目:
go mod init $module_name
$module_name和目录名可以不一样。上述命令会生成go.mod文件,该文件内容形如:
module go-course
go 1.17
require (
github.com/ethereum/go-ethereum v1.10.8
github.com/gin-gonic/gin v1.7.4
)
Go依次从当前项目、GOROOT、GOPATH下寻找依赖包。
- 从当前go文件所在的目录逐级向上查找go.mod文件(假设go.mod位于目录mode_path下),里面定义了module_name,则引入包的路径为"module_name/包相对于mode_path的路径"。
- go标准库提供的包在GOROOT/src下。
- 第三方依赖包在GOPATH/pkg/mod下。
从go1.7开始,go get只负责下载第三方依赖包,并把它加到go.mod文件里,由go install负责安装二进制文件。
- go get github.com/mailru/easyjson会在GOPATH/pkg/mod目录下生成github.com/mailru/easyjson目录。
- go install github.com/mailru/easyjson/easyjson会在GOPATH/bin下生成easyjson二进制可执行文件。
go mod tidy通过扫描当前项目中的所有代码来添加未被记录的依赖至go.mod文件或从go.mod文件中删除不再被使用的依赖。
包引入规则
包的声明
- go文件的第一行声明 package xxx。
- 在包声明的上面可写关于包的注释,包注释也可以专门写在doc.go里。
- 包名跟目录名可以不同。
- 同一个目录下,所有go文件的包名必须一致。
包的引用
- 可以直接使用同目录下其他go文件里的变量、函数、结构体。
- 跨目录使用则需要变量前加入包名,并且引入包所在的目录。
imoprt "go-course/package" //go-course是model名,package是目录名
mypackage.Add() //mypackage是包名,它对应的目录是package
- 在import块里可以引用父目录,也可以引用子目录。
- 引用关系不能构成一个环。
- 在import的目录前面可以给包起一个别名。
imoprt asd "go-course/package"
asd.Add()
init调用链
main函数是go程序的唯一入口,所以main函数只能存在一个。main函数必须位于main包中。在main函数执行之前会先执行init()函数。在一个目录,甚至一个go文件里,init()可以重复定义。引入其他包时,相应包里的init()函数也会在main()函数之前被调用。
import _ "net/http/pprof"
在目录前加一个_,代码里却没有显式地使用这个包里的函数或变量,实际上是想执行这个包里的init()函数。
可见性
- 以小写字母开头命名的函数、变量、结构体只能在本包内访问。
- 以大写字母开头命名的函数、变量、结构体在其他包中也可以访问。
- 如果结构体名字以大写字母开头,而其成员变量、成员方法以小写字母开头,则这样的成员只能在本包内访问。
Go中命名为internal的package,可以被平级目录和上一级目录所访问,更上层的目录不能访问。如下图c目录(internal的上一级目录)及其子孙目录之间可以任意import,但a目录和b目录不能import internal及其下属的所有目录。