How to Write Go Code

Introduction

本文档演示了模块内部简单Go软件包的开发,并介绍了go工具 ,这是获取,构建和安装Go模块,软件包和命令的标准方法.

注意:本文档假定您使用的是Go 1.13或更高版本,并且未设置GO111MODULE环境变量. 如果您正在寻找本文档的较早的预模块版本,请在此处存档.

Code organization

Go程序被组织到软件包中. 是同一目录中一起编译的源文件的集合. 在一个源文件中定义的函数,类型,变量和常量对于同一包中的所有其他源文件可见.

存储库包含一个或多个模块. 模块是一起发布的相关Go软件包的集合. Go存储库通常仅包含一个模块,位于存储库的根目录中. 名为go.mod的文件go.mod那里声明了模块路径 :模块内所有软件包的导入路径前缀. 该模块在包含其go.mod文件的目录以及该目录的子目录中包含go.mod ,直至包含另一个go.mod文件(如果有)的下一个子目录.

请注意,在构建代码之前,无需将代码发布到远程存储库. 可以在本地定义模块,而不必属于存储库. 但是,组织代码是一种好习惯,就像您有一天要发布代码一样.

每个模块的路径不仅充当其软件包的导入路径前缀,而且还指示go命令将其下载到的位置. 例如,为了下载模块golang.org/x/tools中, go命令将查阅资料库以表示https://golang.org/x/tools (描述更这里 ).

An 导入路径 is a string used to import a package. A package's import path is its module path joined with its subdirectory within the module. For example, the module github.com/google/go-cmp contains a package in the directory cmp/. That package's import path is github.com/google/go-cmp/cmp. Packages in the standard library do not have a module path prefix.

Your first program

要编译并运行一个简单的程序,首先选择一个模块路径(我们将使用github.com/user/hello )并创建一个声明它的go.mod文件:

$ mkdir hello # Alternatively, clone it if it already exists in version control.
$ cd hello
$ go mod init github.com/user/hello
go: creating new go.mod: module github.com/user/hello
$ cat go.mod
module github.com/user/hello

go 1.13
$

Go源文件中的第一条语句必须是package name . 可执行命令必须始终使用package main .

接下来,在该目录中创建一个名为hello.go的文件,其中包含以下Go代码:

package main

import "fmt"

func main() {
	fmt.Println("Hello, world.")
}

现在,您可以使用go工具构建并安装该程序:

$ go install github.com/user/hello
$

该命令生成hello命令,生成可执行二进制文件. 然后,将该二进制文件安装为$HOME/go/bin/hello (或在Windows下为%USERPROFILE%\go\bin\hello.exe ). 您可以通过设置GOBIN 环境变量来更改安装目录.

$ go env -w GOBIN=/somewhere/else/bin
$

诸如go install之类的命令适用于包含当前工作目录的模块的上下文. 如果工作目录不在github.com/user/hello模块内, go install可能会失败.

为了方便起见, go命令接受相对于工作目录的路径,如果没有其他路径,则默认使用当前工作目录中的软件包. 因此,在我们的工作目录中,以下命令都是等效的:

$ go install github.com/user/hello
$ go install .
$ go install

接下来,让我们运行该程序以确保其正常工作. 为了更加方便,我们将安装目录添加到PATH以使运行二进制文件变得容易:

# Windows users should consult https://github.com/golang/go/wiki/SettingGOPATH
# for setting %PATH%.
$ export PATH=$PATH:$(go env GOBIN)
$ hello
Hello, world.
$

如果您使用的是源代码控制系统,那么现在将是初始化存储库,添加文件并提交第一个更改的好时机. 同样,此步骤是可选的:您无需使用源代码编写Go代码.

$ git init
Initialized empty Git repository in /home/user/hello/.git/
$ git add go.mod hello.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
 1 file changed, 7 insertion(+)
 create mode 100644 go.mod hello.go
$

Importing packages from your module

让我们编写一个morestrings包,并在hello程序中使用它. 首先,创建一个名为软件包的目录$HOME/hello/morestrings ,然后一个文件名为reverse.go与以下内容该目录:

// Package morestrings implements additional functions to manipulate UTF-8
// encoded strings, beyond what is provided in the standard "strings" package.
package morestrings

// ReverseRunes returns its argument string reversed rune-wise left to right.
func ReverseRunes(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)
}

因为我们的ReverseRunes函数以大写字母开头,所以将其导出 ,并且可以在导入morestrings包的其他包中使用.

让我们测试一下该软件包可以通过go build编译:

$ cd $HOME/hello/morestrings
$ go build
$

这不会产生输出文件. 而是将已编译的程序包保存在本地构建缓存中.

确认morestrings软件包已生成后,让我们从hello程序中使用它. 为此,请修改原始的$HOME/hello/hello.go以使用morestrings包:

package main

import (
	"fmt"

	"github.com/user/hello/morestrings"
)

func main() {
	fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
}

安装hello程序:

$ go install github.com/user/hello

运行新版本的程序,您应该看到一条新的反向消息:

$ hello
Hello, Go!

Importing packages from remote modules

导入路径可以描述如何使用修订控制系统(例如Git或Mercurial)获取软件包源代码. go工具使用此属性来自动从远程存储库获取软件包. 例如,要在程序中使用github.com/google/go-cmp/cmp

package main

import (
	"fmt"

	"github.com/user/hello/morestrings"
	"github.com/google/go-cmp/cmp"
)

func main() {
	fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
	fmt.Println(cmp.Diff("Hello World", "Hello Go"))
}

当您运行诸如go installgo buildgo run ,远程模块将自动添加到go.mod文件中(并下载):

$ go install github.com/user/hello
$ hello
Hello, Go!
  string(
- 	"Hello World",
+ 	"Hello Go",
  )
$ cat go.mod
module github.com/user/hello

go 1.13

require github.com/google/go-cmp v0.3.1
$

模块的路径不必与其存储库的URL匹配,但是此约定是使Go包可供他人使用的最简单方法. 有关通过go工具使用远程模块的更多信息,请参阅go help importpath使用Go模块 .

Testing

Go具有由go test命令和testing包组成的轻量级测试框架.

通过创建一个名称以_test.go结尾的文件来编写测试,该文件包含名为TestXXX且具有签名func (t *testing.T) . 测试框架运行每个这样的功能. 如果该函数调用诸如t.Errort.Fail类的失败函数,则认为测试已失败.

通过创建包含以下Go代码的文件$HOME/hello/morestrings/reverse_test.go ,将测试添加到morestrings包中.

package morestrings

import "testing"

func TestReverseRunes(t *testing.T) {
	cases := []struct {
		in, want string
	}{
		{"Hello, world", "dlrow ,olleH"},
		{"Hello, 世界", "界世 ,olleH"},
		{"", ""},
	}
	for _, c := range cases {
		got := ReverseRunes(c.in)
		if got != c.want {
			t.Errorf("ReverseRunes(%q) == %q, want %q", c.in, got, c.want)
		}
	}
}

然后使用go test运行go test

$ go test
PASS
ok  	github.com/user/morestrings 0.165s
$

运行go help test并查看测试包文档以获取更多详细信息.

What's next

订阅golang公告邮件列表,以便在发布新的稳定版Go时收到通知.

有关编写清晰,惯用的Go代码的提示,请参见有效的Go .

参加"围棋之旅"以学习适当的语言.

请访问文档页面,获取有关Go语言及其库和工具的一系列深入文章.

Getting help

要获得实时帮助,请在社区运行的Gophers Slack服务器中询问有用的gopher( 在此处获取邀请).

讨论Go语言的正式邮件清单是Go Nuts .

使用Go问题跟踪器报告错误.

by  ICOPY.SITE