Go 语言实战 第 3 章 打包和工具链
在 Go 语言中,包是个非常重要的概念。
其设计理念是使用包来封装不同语义单元的功能。
所有的 .go 文件,除了空行和注释,都应该在第一行声明自己所属的包。
每个包都在单独的目录里。
同一个目录下的所有 .go 文件必须声明同一个包名。
给包命名的惯例是使用包所在目录的名字。
给包及其目录命名时,应该使用简洁、清晰且全小写的名字。
main 包
在 Go 语言中,命名为 main 的包具有特殊的含义。
所有用 Go 语言编译的可执行程序都必须有一个名叫 main 的包。main()
函数是程序的入口。
程序编译时,会使用声明为 main 包的代码所在的目录的目录名作为二进制可执行文件的文件名。
导入
使用 import
语句导入包。
编译器会使用 Go 环境变量设置的路径,通过引入的相对路径来查找磁盘上的包。
标准库中的包会在安装 Go 的位置找到。Go 开发者创建的包会在 GOPATH
环境变量指定的目录里查找。GOPATH
指定的这些目录就是开发者的个人工作空间。
一旦编译器找到一个满足 import
语句的包,就停止进一步的查找。
编译器会首先查找 Go 的安装目录,然后才会按顺序查找 GOPATH
变量里列出的目录。
Go 语言的工具链本身支持从 DVCS(Distributed Version Control Systems)网站获取源代码。
这个过程使用 go get
命令完成。
import "github.com/spf13/viper"
命名导入
导入的多个包具有相同的名字时,可以使用命名导入。
import (
"fmt"
myfmt "mylib/fmt"
)
导入未在代码中使用的包时,可以使用空白标识符(_
)。
import (
_ "fmt"
)
init 函数
所有被编译器发现的 init
函数都会安排在 main
函数之前执行。init
函数用在设置包、初始化变量或者其它要在程序运行前优先完成的引导工作。
使用 Go 的工具
查看 Go 提供的命令:
PS C:\go\src\hello> go
Go is a tool for managing Go source code.
Usage:
go <command> [arguments]
The commands are:
bug start a bug report
build compile packages and dependencies
clean remove object files and cached files
doc show documentation for package or symbol
env print Go environment information
fix update packages to use new APIs
fmt gofmt (reformat) package sources
generate generate Go files by processing source
get add dependencies to current module and install them
install compile and install packages and dependencies
list list packages or modules
mod module maintenance
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet report likely mistakes in packages
Use "go help <command>" for more information about a command.
Additional help topics:
buildmode build modes
c calling between Go and C
cache build and test caching
environment environment variables
filetype file types
go.mod the go.mod file
gopath GOPATH environment variable
gopath-get legacy GOPATH go get
goproxy module proxy protocol
importpath import path syntax
modules modules, module versions, and more
module-get module-aware go get
module-auth module authentication using go.sum
module-private module configuration for non-public modules
packages package lists and patterns
testflag testing flags
testfunc testing functions
Use "go help <topic>" for more information about that topic.
编译 & 清除
PS C:\go\src\hello> go build .\hello.go
PS C:\go\src\hello> go clean .\hello.go
大部分 Go 工具命令都会接受一个包名作为参数。
有些命令可以简写。如 build ,此时默认使用当前目录来编译。
PS C:\go\src\hello> go build
可以直接指定包,此时还可以使用通配符。三个点表示匹配所有字符串。
PS C:\go\src> go build .\github.com\goinaction\code\chapter3\wordcount
PS C:\go\src> go build .\github.com\goinaction\code\chapter3\wordcount\...
文件在当前目录时,可以使用段路径:文件名 或者 .
。
PS C:\go\src\github.com\goinaction\code\chapter3\wordcount> go build .\wordcount.go
PS C:\go\src\github.com\goinaction\code\chapter3\wordcount> go build .
编译和运行一起执行时可以使用 run 命令。
PS C:\go\src\hello> go run .\hello.go
Hello World!
go vet: 帮助开发人员检测代码的常见错误:
Printf
类函数调用时,类型匹配错误的参数;- 定义常用的方法时,方法签名的错误;
- 错误的结构标签;
- 没有指定字段名的结构字面量。
go fmt:自动格式指定的源代码并保存。
go doc:在终端上打印文档。
godoc:启动一个 Web 服务器,通过点击的方式查看 Go 语言的包的文档。支持开发者自己写的代码。
godoc -http:6060
代码文档规则:
- 在标识符之前,把想要的文档作为注释加入到代码中。
- 如果想给包写一段文字量比较大的文档,可以在工程里包含一个叫做 doc.go 的文件,使用同样的包名,并把包的介绍使用注释加在包声明之前。
- 多行注释使用
\* *\
符号。
创建代码库以分享:
- 包应该在代码库的根目录中。
- 包可以非常小。
- 对代码执行
go fmt
。 - 给代码写文档。
依赖管理
- Keith Rarik:
godep
- Daniel Theophanes:
vendor
- Gustavo Niemeyer:
gopkg.in
godep 和 vendor 使用第三方 verdoring 导入路径重写特性解决依赖问题。
gb
gb 是一个由 Go 社区成员开发的全新的构建工具。
gb 工程会区分开发人员写的代码和开发人员需要依赖的代码(第三方代码)。
gb 一个最好的特点是,不需要重写导入路径。
gb 工具首先会在 $PROJECT/srv/
目录查找代码,如果找不到,会在 $PROJECT/vendor/src
目录里查找。
自己写的代码在工程目录的 src 目录中,第三方依赖代码在工程目录的 verdor/src 目录中。
gb 工程和 Go 官方工具链(包括 go get)并不兼容。
gb build all
更多 gb 特性可以访问 getgb.io 。
小结
- 在 Go 语言中包是组织代码的基本单位。
- 环境变量 GOPATH 决定了 Go 源代码在磁盘上被保存、编译和安装的位置。
- 可以为每个工程设置不同的 GOPATH,以保持源代码和依赖的隔离。
- go 工具是在命令行上工作的最好工具。
- 开发人员可以使用 go get 来获取别人的包并将其安装到自己的 GOPATH 指定的目录。
- 想要为别人创建包很简单,只要把源代码放到公用代码库,并遵守一些简单规则就可以。
- Go 语言在设计时将分享代码作为语言的核心特性和驱动力。
- 推荐使用依赖管理工具来管理依赖。
- 由很多社区开发的依赖管理工具,如 godep、vendor 和 gb 。