如何编写 Go 代码
7 分钟阅读
How to Write Go Code - 如何编写 Go 代码
简介
本文档演示了在模块中开发一个简单的Go包,并介绍了go tool,这是获取、构建和安装Go模块、包和命令的标准方式。
注意:本文档假设您使用的是
Go 1.13
或更高版本,并且没有设置GO111MODULE
环境变量。如果您要找的是本文档的旧版,即模块之前的版本,它被存档在这里。
代码组织
Go程序被组织成包。包是同一目录下的源文件的集合,这些文件被编译在一起。在一个源文件中定义的函数、类型、变量和常量对同一包内的所有其他源文件都是可见的。
代码库包含一个或多个模块。模块是相关 Go 包的集合,它们被一起发布。一个 Go 代码库通常只包含一个模块,位于代码库的根部。那里有一个名为go.mod
的文件声明了模块路径:模块内所有包的导入路径前缀。该模块包含其go.mod
文件的所在目录中的软件包,以及该目录的子目录(的软件包),直到包含另一个go.mod
文件的所在的子目录(的软件包)(如果有的话)。
请注意,您不需要在构建之前将您的代码发布到一个远程仓库。一个模块可以在本地定义而不属于一个版本库。然而,组织您的代码是一个好习惯,就像您有一天会发布它一样。
每个模块的路径不仅作为其包的导入路径前缀,而且还指出go
命令应该在哪里下载它。例如,为了下载golang.org/x/tools
模块,go命令会查阅https://golang.org/x/tools(这里有更多描述)所指示的仓库。
导入路径是一个用于导入软件包的字符串。一个包的导入路径是它的模块路径与模块中的子目录相连接。例如,模块github.com/google/go-cmp
在cmp/
目录下包含一个包。该包的导入路径是github.com/google/go-cmp/cmp
。标准库中的包没有模块路径前缀。
您的第一个程序
要编译和运行一个简单的程序,首先选择一个模块路径(我们将使用 example/user/hello
),并创建一个声明它的 go.mod
文件:
|
|
Go源文件中的第一条语句必须是package name
。可执行命令必须始终使用package main
。
接下来,在该目录下创建一个名为hello.go
的文件,包含以下Go代码:
|
|
现在您可以用go
工具构建和安装该程序:
|
|
这个命令构建了hello
命令,产生了一个可执行的二进制文件。然后,它将该二进制文件安装为$HOME/go/bin/hello
(或者,在Windows下,%USERPROFILE%\gobinhello.exe
)。
安装目录是由GOPATH
和GOBIN
环境变量控制的。如果设置了GOBIN
,二进制文件将被安装到该目录。如果设置了GOPATH
,二进制文件将被安装到GOPATH
列表中第一个目录的bin
子目录中。否则,二进制文件将被安装到默认的 GOPATH
($HOME/go
或 %USERPROFILE%\go
)的 bin
子目录。
您可以使用go env
命令为未来的go
命令可移植地设置环境变量的默认值:
|
|
要取消先前由go env -w
设置的变量,请使用go env -u
。
|
|
像go install
这样的命令在包含当前工作目录的模块上下文中应用。如果工作目录不在example/user/hello
模块内,go install
可能会失败。
为了方便起见,go
命令接受相对于工作目录的路径,如果没有给出其他路径,则默认为当前工作目录下的软件包。因此在我们的工作目录中,以下命令都是等价的。
|
|
接下来,让我们运行该程序,以确保它能工作。为了方便起见,我们将安装目录添加到我们的PATH
中,以使运行二进制文件更加容易:
|
|
如果您使用的是源码控制系统,现在是初始化代码库的好时机,添加文件,并提交您的第一个改动。同样,这一步是可选的:您不需要使用源码控制来编写Go代码。
|
|
go
命令通过请求相应的 HTTPS URL 并读取嵌入在 HTML 响应中的元数据来定位包含给定模块路径的代码库(见 go help importpath
)。许多托管服务已经为包含Go代码库提供了元数据,所以让您的模块供他人使用的最简单方法通常是使其模块路径与代码库的URL相匹配。
在您的模块中导入包
让我们写一个morestrings
包并从hello
程序中使用它。首先,为该包创建一个名为$HOME/hello/morestrings
的目录,然后在该目录下创建一个名为reverse.go
的文件,内容如下:
|
|
因为我们的ReverseRunes
函数以大写字母开头,所以它是可导出的,可以在其他包中通过导入morestrings
包来使用该函数。
让我们用go build
来测试一下这个包的编译情况:
|
|
这不会产生一个输出文件。相反,它会把编译好的包保存在本地的构建缓存中。
在确认了morestrings
包的构建之后,让我们在hello
程序中使用它。要做到这一点,请修改您原来的$HOME/hello/hello.go
以使用morestrings
包:
|
|
安装hello
程序:
|
|
运行新版本的程序,您应该看到一个新的、反转的信息:
|
|
从远程模块导入包
导入路径可以描述如何使用Git
或Mercurial
等修订控制系统获得软件包的源代码。go
工具使用这个属性来自动从远程代码库获取包。例如,要在您的程序中使用github.com/google/go-cmp/cmp
:
|
|
现在您有了对外部模块的依赖,您需要下载该模块
并在您的go.mod
文件中记录其版本。go mod tidy
命令为导入的软件包添加缺少的模块需求,并删除不再使用的模块需求。
|
|
模块的依赖项被自动下载到GOPATH
环境变量所指示的目录的pkg/mod
子目录中。一个特定版本的模块的下载内容在所有需要(require
)该版本的其他模块中共享,因此go
命令将这些文件和目录标记为只读。要删除所有下载的模块
,您可以在go clean
中传递-modcache
标志:
|
|
测试
Go有一个由go test
命令和testing
包组成的轻量级测试框架。
您可以通过创建一个名称以_test.go
结尾的文件来编写测试,该文件包含名为TestXXX
的函数,其签名为func(t *testing.T)
。测试框架运行每个这样的函数;如果在该函数调用一个失败的函数,如t.Error
或t.Fail
,则认为测试失败。
通过创建包含以下Go代码的$HOME/hello/morestrings/reverse_test.go
文件,向morestrings
包添加一个测试。
|
|
然后用go test
运行该测试:
|
|
运行go help test
,更多细节请看testing package documentation。
下一步
订阅 golang-announce 邮件列表,以便在 Go 的新稳定版本发布时获得通知。
请参阅 Effective Go 以了解编写清晰、简洁的 Go 代码的技巧。
参加 A Tour of Go来学习这门语言。
访问文档页面,了解有关 Go 语言及其库和工具的一系列深度文章。
获得帮助
要获得实时帮助,请向社区管理的 gophers Slack server (在此获取邀请)中愿意帮忙的 gophers 咨询。
用于讨论 Go 语言的官方邮件列表是 Go Nuts。
使用 Go issue tracker报告 bugs。