This document demonstrates the development of a simple Go package and introduces the go tool, the standard way to fetch, build, and install Go packages and commands.
本文档展示了一个简单Go包的开发,并介绍了用go工具来获取、 构建并安装Go包及命令的标准方式。
The go
tool requires you to organize your code in a specific way. Please read this document carefully. It explains the simplest way to get up and running with your Go installation.
go
工具需要你按照指定的方式来组织代码。请仔细阅读本文档, 它说明了如何以最简单的方式来准备并运行你的Go安装。
A similar explanation is available as a screencast.
类似的视频讲解可在此处观看。
The go
tool is designed to work with open source code maintained in public repositories. Although you don't need to publish your code, the model for how the environment is set up works the same whether you do or not.
go
工具为公共代码仓库中维护的开源代码而设计。 无论你会不会公布代码,该模型设置工作环境的方法都是相同的。
Go code must be kept inside a _workspace_. A workspace is a directory hierarchy with three directories at its root:
Go代码必须放在工作空间内。它其实就是一个目录,其中包含三个子目录:
src
contains Go source files organized into packages (one package per directory),pkg
contains package objects, andbin
contains executable commands.src
目录包含Go的源文件,它们被组织成包(每个目录都对应一个包),pkg
目录包含包对象,bin
目录包含可执行命令。The go
tool builds source packages and installs the resulting binaries to the pkg
and bin
directories.
go
工具用于构建源码包,并将其生成的二进制文件安装到 pkg
和 bin
目录中。
The src
subdirectory typically contains multiple version control repositories (such as for Git or Mercurial) that track the development of one or more source packages.
src
子目录通常包会含多种版本控制的代码仓库(例如Git或Mercurial), 以此来跟踪一个或多个源码包的开发。
To give you an idea of how a workspace looks in practice, here's an example:
以下例子展现了实践中工作空间的概念:
bin/
hello # command executable
outyet # command executable
pkg/
linux_amd64/
github.com/golang/example/
stringutil.a # package object
src/
[github.com/golang/example/](https://github.com/golang/example/)
.git/ # Git repository metadata
hello/
hello.go # command source
outyet/
main.go # command source
main_test.go # test source
stringutil/
reverse.go # package source
reverse_test.go # test source
bin/
streak # 可执行命令
todo # 可执行命令
pkg/
linux_amd64/
code.google.com/p/goauth2/
oauth.a # 包对象
github.com/nf/todo/
task.a # 包对象
src/
code.google.com/p/goauth2/
.hg/ # mercurial 代码库元数据
oauth/
oauth.go # 包源码
oauth_test.go # 测试源码
github.com/nf/
streak/
.git/ # git 代码库元数据
oauth.go # 命令源码
streak.go # 命令源码
todo/
.git/ # git 代码库元数据
task/
task.go # 包源码
todo.go # 命令源码
This workspace contains one repository (example
) comprising two commands (hello
and outyet
) and one library (stringutil
).
A typical workspace would contain many source repositories containing many packages and commands. Most Go programmers keep all their Go source code and dependencies in a single workspace.
此工作空间包含三个代码库(goauth2
、streak
和 todo
),两个命令(streak
和 todo
) 以及两个库(oauth
和 task
)。
Commands and libraries are built from different kinds of source packages. We will discuss the distinction later.
命令和库从不同的源码包编译而来。稍后我们会对讨论它的特性。
GOPATH
environment variableGOPATH
环境变量The GOPATH
environment variable specifies the location of your workspace. It is likely the only environment variable you'll need to set when developing Go code.
GOPATH
环境变量指定了你的工作空间位置。它或许是你在开发Go代码时, 唯一需要设置的环境变量。
To get started, create a workspace directory and set GOPATH
accordingly. Your workspace can be located wherever you like, but we'll use $HOME/work
in this document. Note that this must not be the same path as your Go installation. (Another common setup is to set GOPATH=$HOME
.)
首先创建一个工作空间目录,并设置相应的 GOPATH
。你的工作空间可以放在任何地方, 在此文档中我们使用 $HOME/work
。注意,它绝对不能和你的Go安装目录相同。 (另一种常见的设置是 GOPATH=$HOME
。)
$ **mkdir $HOME/work**
$ **export GOPATH=$HOME/work**
For convenience, add the workspace's bin
subdirectory to your PATH
:
作为约定,请将此工作空间的 bin
子目录添加到你的 PATH
中:
$ **export PATH=$PATH:$GOPATH/bin**
To learn more about setting up the GOPATH
environment variable, please see go help gopath
The packages from the standard library are given short paths such as "fmt"
and "net/http"
. For your own packages, you must choose a base path that is unlikely to collide with future additions to the standard library or other external libraries.
标准库中的包有给定的短路径,比如 "fmt"
和 "net/http"
。 对于你自己的包,你必须选择一个基本路径,来保证它不会与将来添加到标准库, 或其它扩展库中的包相冲突。
If you keep your code in a source repository somewhere, then you should use the root of that source repository as your base path. For instance, if you have a GitHub account at github.com/user
, that should be your base path.
如果你将你的代码放到了某处的源码库,那就应当使用该源码库的根目录作为你的基本路径。 例如,若你在 GitHub 上有账户 github.com/user
那么它就应该是你的基本路径。
Note that you don't need to publish your code to a remote repository before you can build it. It's just a good habit to organize your code as if you will publish it someday. In practice you can choose any arbitrary path name, as long as it is unique to the standard library and greater Go ecosystem.
注意,在你能构建这些代码之前,无需将其公布到远程代码库上。只是若你某天会发布它, 这会是个好习惯。在实践中,你可以选择任何路径名,只要它对于标准库和更大的Go生态系统来说, 是唯一的就行。
We'll use github.com/user
as our base path. Create a directory inside your workspace in which to keep source code:
我们将使用 github.com/user
作为基本路径。在你的工作空间里创建一个目录, 我们将源码存放到其中:
$ **mkdir -p $GOPATH/src/github.com/user**
To compile and run a simple program, first choose a package path (we'll use github.com/user/hello
) and create a corresponding package directory inside your workspace:
要编译并运行简单的程序,首先要选择包路径(我们在这里使用 github.com/user/hello
),并在你的工作空间内创建相应的包目录:
$ **mkdir $GOPATH/src/github.com/user/hello**
Next, create a file named hello.go
inside that directory, containing the following Go code.
接着,在该目录中创建名为 hello.go
的文件,其内容为以下Go代码:
package main
import "fmt"
func main() {
fmt.Printf("Hello, world.\\n")
}
Now you can build and install that program with the go
tool:
现在你可以用 go
工具构建并安装此程序了:
$ go install github.com/user/hello
Note that you can run this command from anywhere on your system. The go
tool finds the source code by looking for the github.com/user/hello
package inside the workspace specified by GOPATH
.
注意,你可以在系统的任何地方运行此命令。go
工具会根据 GOPATH
指定的工作空间,在 github.com/user/hello
包内查找源码。
You can also omit the package path if you run go install
from the package directory:
若在从包目录中运行 go install
,也可以省略包路径:
$ **cd $GOPATH/src/github.com/user/hello**
$ go install
This command builds the hello
command, producing an executable binary. It then installs that binary to the workspace's bin
directory as hello
(or, under Windows, hello.exe
). In our example, that will be $GOPATH/bin/hello
, which is $HOME/work/bin/hello
.
此命令会构建 hello
命令,产生一个可执行的二进制文件。 接着它会将该二进制文件作为 hello
(在 Windows 下则为 hello.exe
)安装到工作空间的 bin
目录中。 在我们的例子中为 $GOPATH/bin/hello
,具体一点就是 $HOME/go/bin/hello
。
The go
tool will only print output when an error occurs, so if these commands produce no output they have executed successfully.
go
工具只有在发生错误时才会打印输出,因此若这些命令没有产生输出, 就表明执行成功了。
You can now run the program by typing its full path at the command line:
现在,你可以在命令行下输入它的完整路径来运行它了:
$ **$GOPATH/bin/hello**
Hello, world.
Or, as you have added $GOPATH/bin
to your PATH
, just type the binary name:
若你已经将 $GOPATH/bin
添加到 PATH
中了,只需输入该二进制文件名即可:
$ hello
Hello, world.
If you're using a source control system, now would be a good time to initialize a repository, add the files, and commit your first change. Again, this step is optional: you do not need to use source control to write Go code.
若你使用源码控制系统,那现在就该初始化仓库,添加文件并提交你的第一次更改了。 再次强调,这一步是可选的:你无需使用源码控制来编写Go代码。
$ **cd $GOPATH/src/github.com/user/hello**
$ git init
Initialized empty Git repository in /home/user/work/src/github.com/user/hello/.git/
$ git add hello.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
1 file changed, 1 insertion(+)
create mode 100644 hello.go
Pushing the code to a remote repository is left as an exercise for the reader.
将代码推送到远程仓库就留作读者的练习了。
Let's write a library and use it from the hello
program.
让我们编写一个库,并让 hello
程序来使用它。
Again, the first step is to choose a package path (we'll use github.com/user/stringutil
) and create the package directory:
同样,第一步还是选择包路径(我们将使用 github.com/user/stringutil
) 并创建包目录:
$ **mkdir $GOPATH/src/github.com/user/stringutil**
Next, create a file named reverse.go
in that directory with the following contents.
接着,在该目录中创建名为 reverse.go
的文件,内容如下:
// Package stringutil contains utility functions for working with strings.
package stringutil
// Reverse returns its argument string reversed rune-wise left to right.
func Reverse(s string) string {
r := \[\]rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r\[i\], r\[j\] = r\[j\], r\[i\]
}
return string(r)
}
// stringutil 包含有用于处理字符串的工具函数。
package stringutil
// Reverse 将其实参字符串以符文为单位左右反转。
func Reverse(s string) string {
r := \[\]rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r\[i\], r\[j\] = r\[j\], r\[i\]
}
return string(r)
}
Now, test that the package compiles with go build
:
现在用 go build
命令来测试该包的编译:
$ go build github.com/user/stringutil
Or, if you are working in the package's source directory, just:
当然,若你在该包的源码目录中,只需执行:
$ go build
This won't produce an output file. To do that, you must use go install
, which places the package object inside the pkg
directory of the workspace.
即可。这不会产生输出文件。想要输出的话,必须使用 go install
命令,它会将包的对象放到工作空间的 pkg
目录中。
After confirming that the stringutil
package builds, modify your original hello.go
(which is in $GOPATH/src/github.com/user/hello
) to use it:
确认 stringutil
包构建完毕后,修改原来的 hello.go
文件(它位于 $GOPATH/src/github.com/user/hello
)去使用它:
package main
import (
"fmt"
**"github.com/user/stringutil"**
)
func main() {
fmt.Printf(stringutil.Reverse("!oG ,olleH"))
}
Whenever the go
tool installs a package or binary, it also installs whatever dependencies it has. So when you install the hello
program
无论是安装包还是二进制文件,go
工具都会安装它所依赖的任何东西。 因此当我们通过
$ go install github.com/user/hello
the stringutil
package will be installed as well, automatically.
来安装 hello
程序时,stringutil
包也会被自动安装。
Running the new version of the program, you should see a new, reversed message:
运行此程序的新版本,你应该能看到一条新的,反向的信息:
$ hello
Hello, Go!
After the steps above, your workspace should look like this:
做完上面这些步骤后,你的工作空间应该是这样的:
bin/
hello # command executable
pkg/
linux_amd64/ # this will reflect your OS and architecture
github.com/user/
stringutil.a # package object
src/
github.com/user/
hello/
hello.go # command source
stringutil/
reverse.go # package source
bin/
hello # 可执行命令
pkg/
linux_amd64/ # 这里会反映出你的操作系统和架构
github.com/user/
stringutil.a # 包对象
src/
github.com/user/
hello/
hello.go # 命令源码
stringutil/
reverse.go # 包源码
Note that go install
placed the stringutil.a
object in a directory inside pkg/linux_amd64
that mirrors its source directory. This is so that future invocations of the go
tool can find the package object and avoid recompiling the package unnecessarily. The linux_amd64
part is there to aid in cross-compilation, and will reflect the operating system and architecture of your system.
注意 go install
会将 stringutil.a
对象放到 pkg/linux_amd64
目录中,它会反映出其源码目录。 这就是在此之后调用 go
工具,能找到包对象并避免不必要的重新编译的原因。 linux_amd64
这部分能帮助跨平台编译,并反映出你的操作系统和架构。
Go command executables are statically linked; the package objects need not be present to run Go programs.
Go的可执行命令是静态链接的;在运行Go程序时,包对象无需存在。
The first statement in a Go source file must be
Go源文件中的第一个语句必须是
package name
package 名称
where _name_
is the package's default name for imports. (All files in a package must use the same _name_
.)
这里的 **名称**
即为导入该包时使用的默认名称。 (一个包中的所有文件都必须使用相同的 **名称**
。)
Go's convention is that the package name is the last element of the import path: the package imported as "crypto/rot13
" should be named rot13
.
Go的约定是包名为导入路径的最后一个元素:作为 “crypto/rot13
” 导入的包应命名为 rot13
。
Executable commands must always use package main
.
可执行命令必须使用 package main
。
There is no requirement that package names be unique across all packages linked into a single binary, only that the import paths (their full file names) be unique.
链接成单个二进制文件的所有包,其包名无需是唯一的,只有导入路径(它们的完整文件名) 才是唯一的。
See Effective Go to learn more about Go's naming conventions.
共多关于Go的命名约定见 实效Go编程。
Go has a lightweight test framework composed of the go test
command and the testing
package.
Go拥有一个轻量级的测试框架,它由 go test
命令和 testing
包构成。
You write a test by creating a file with a name ending in _test.go
that contains functions named TestXXX
with signature func (t *testing.T)
. The test framework runs each such function; if the function calls a failure function such as t.Error
or t.Fail
, the test is considered to have failed.
你可以通过创建一个名字以 _test.go
结尾的,包含名为 TestXXX
且签名为 func (t *testing.T)
函数的文件来编写测试。 测试框架会运行每一个这样的函数;若该函数调用了像 t.Error
或 t.Fail
这样表示失败的函数,此测试即表示失败。
Add a test to the stringutil
package by creating the file $GOPATH/src/github.com/user/stringutil/reverse_test.go
containing the following Go code.
我们可通过创建文件 $GOPATH/src/github.com/user/stringutil/reverse_test.go
来为 stringutil
添加测试,其内容如下:
package stringutil
import "testing"
func TestReverse(t *testing.T) {
cases := \[\]struct {
in, want string
}{
{"Hello, world", "dlrow ,olleH"},
{"Hello, 世界", "界世 ,olleH"},
{"", ""},
}
for _, c := range cases {
got := Reverse(c.in)
if got != c.want {
t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
}
}
}
Then run the test with go test
:
接着使用 go test
运行该测试:
$ go test github.com/user/stringutil
ok github.com/user/stringutil 0.165s
As always, if you are running the go
tool from the package directory, you can omit the package path:
同样,若你在包目录下运行 go
工具,也可以忽略包路径
$ go test
ok github.com/user/stringutil 0.165s
Run [go help test](https://go-zh.org/cmd/go/#hdr-Test_packages)
and see the testing package documentation for more detail.
更多详情可运行 [go help test](https://go-zh.org/cmd/go/#hdr-%E6%B5%8B%E8%AF%95%E5%8C%85)
或从 testing 包文档 中查看。
An import path can describe how to obtain the package source code using a revision control system such as Git or Mercurial. The go
tool uses this property to automatically fetch packages from remote repositories. For instance, the examples described in this document are also kept in a Git repository hosted at GitHub [github.com/golang/example](https://github.com/golang/example)
. If you include the repository URL in the package's import path, go get
will fetch, build, and install it automatically:
像Git或Mercurial这样的版本控制系统,可根据导入路径的描述来获取包源代码。go
工具可通过此特性来从远程代码库自动获取包。例如,本文档中描述的例子也可存放到Google Code上的Mercurial仓库 [code.google.com/p/go.example](http://code.google.com/p/go.example)
中,若你在包的导入路径中包含了代码仓库的URL,go get
就会自动地获取、 构建并安装它:
$ go get github.com/golang/example/hello
$ **$GOPATH/bin/hello**
Hello, Go examples!
If the specified package is not present in a workspace, go get
will place it inside the first workspace specified by GOPATH
. (If the package does already exist, go get
skips the remote fetch and behaves the same as go install
.)
若指定的包不在工作空间中,go get
就会将会将它放到 GOPATH
指定的第一个工作空间内。(若该包已存在,go get
就会跳过远程获取, 其行为与 go install
相同)
After issuing the above go get
command, the workspace directory tree should now look like this:
在执行完上面的go get
命令后,工作空间的目录树看起来应该是这样的:
bin/
hello # command executable
pkg/
linux_amd64/
github.com/golang/example/
stringutil.a # package object
github.com/user/
stringutil.a # package object
src/
github.com/golang/example/
.git/ # Git repository metadata
hello/
hello.go # command source
stringutil/
reverse.go # package source
reverse_test.go # test source
github.com/user/
hello/
hello.go # command source
stringutil/
reverse.go # package source
reverse_test.go # test source
bin/
hello # 可执行命令
pkg/
linux_amd64/
code.google.com/p/go.example/
stringutil.a # 包对象
github.com/user/
stringutil.a # 包对象
src/
code.google.com/p/go.example/
hello/
hello.go # 命令源码
stringutil/
reverse.go # 包源码
reverse_test.go # 测试源码
github.com/user/
hello/
hello.go # 命令源码
stringutil/
reverse.go # 包源码
reverse_test.go # 测试源码
The hello
command hosted at GitHub depends on the stringutil
package within the same repository. The imports in hello.go
file use the same import path convention, so the go get
command is able to locate and install the dependent package, too.
hello
命令及其依赖的 stringutil
包都托管在Google Code上的同一代码库中。hello.go
文件使用了同样的导入路径约定, 因此 go get
命令也能够定位并安装其依赖包。
import "github.com/golang/example/stringutil"
This convention is the easiest way to make your Go packages available for others to use. The Go Wiki and godoc.org provide lists of external Go projects.
遵循此约定可让他人以最简单的方式使用你的Go包。 Go维基 与 godoc.org 提供了外部Go项目的列表。
For more information on using remote repositories with the go
tool, see [go help importpath](https://go-zh.org/cmd/go/#hdr-Remote_import_paths)
.
通过 go
工具使用远程代码库的更多详情,见 [go help remote](https://go-zh.org/cmd/go/#hdr-%E8%BF%9C%E7%A8%8B%E5%AF%BC%E5%85%A5%E8%B7%AF%E5%BE%84%E8%AF%AD%E6%B3%95)
。
Subscribe to the golang-announce mailing list to be notified when a new stable version of Go is released.
订阅 golang-announce 邮件列表来获取Go的稳定版发布信息。
See Effective Go for tips on writing clear, idiomatic Go code.
关于如何编写清晰、地道的Go代码的技巧,见实效Go编程。
Take A Tour of Go to learn the language proper.
要学习Go语言,请跟随Go语言之旅。
Visit the documentation page for a set of in-depth articles about the Go language and its libraries and tools.
关于Go语言的深入性文章及其库和工具,见文档页面。
For real-time help, ask the helpful gophers in #go-nuts
on the Freenode IRC server.
要获取实时帮助,请询问 Freenode IRC 上 #go-nuts
中的 Gopher 们。
The official mailing list for discussion of the Go language is Go Nuts.
Go 语言的官方讨论邮件列表为 Go Nuts。
Report bugs using the Go issue tracker.
请使用Go 问题跟踪器报告 Bug。
构建版本 devel +f22911f Thu Apr 16 05:55:22 2015 +0000.
除特别注明外, 本页内容均采用知识共享-署名(CC-BY)3.0协议授权,代码采用BSD协议授权。
服务条款 | 隐私政策
Original url: Access
Created at: 2019-05-29 16:48:26
Category: default
Tags: none
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论