How to Write Go Code

How to Write Go Code

Code Organization

  • package: a collection of source files in the same directory that are compiled together
  • module: a collection of related Go packages that are released together
  • go.mod declares the module path: the import path prefix for all packages within the module
  • import path: a string used to import a package

First Program

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

go 1.14
$
  • Go 的源文件中第一个 statement 必须是 package 的名字,一个可执行的文件必须使用 package main

  • 创建 hello.go

package main

import "fmt"

func main() {
	fmt.Println("Hello, world.")
}
  • build and install
$ go install example.com/user/hello
$
  • 二进制文件装在 $HOME/go/bin/hello

  • 安装的目录由 GOPATH, GOBIN 来控制

  • 假如 GOBIN 不为空,二进制文件会安装到 GOBIN 指定的文件夹中

  • 假如 GOPATH 不为空,二进制文件会安装到 GOPATH 第一个路径下的 bin 文件夹中

  • 否则,默认安装在 $HOME/go 下面

  • 可以使用 go env 来设置 GOBIN

$ go env -w GOBIN=/somewhere/else/bin
$
  • 解除设置
$ go env -u GOBIN
$
  • go install 作用在包含当前工作区的 module 上下文内,假如当前工作区不在 module 之内,go install 会失败
  • go 可以接受相对路径,假如不给路径的话,默认是当前工作区下的包中进行,所以在适当的工作区中,以下三个命令是等效的:
$ go install example.com/user/hello
$ go install .
$ go install
  • 添加安装路径到路径中去,然后执行:
# Windows users should consult https://github.com/golang/go/wiki/SettingGOPATH
# for setting %PATH%.
$ export PATH=$PATH:$(dirname $(go list -f '{{.Target}}' .))
$ hello
Hello, world.
$

Importing packages from your module

  • 写一个 morestrings 的包,首先创建 $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 开头是大写字母,说明它是 exported ,可以用在其他的 package 里面
  • go build 来编译一下:
$ cd $HOME/hello/morestrings
$ go build
$
  • 没有输出,编译好的包会存在本地的编译缓存中
  • 修改 $HOME/hello/hello.go 来使用这个 morestrings 的包:
package main

import (
	"fmt"

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

func main() {
	fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
}
  • 安装:
$ go install example.com/user/hello
  • 执行:
$ hello
Hello, Go!

Importing packages from remote modules

  • 可以 import 远程的 module
package main

import (
	"fmt"

	"example.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 install, go build, go run,go 会自动下载远程的 module 并将其版本信息记录在 go.mod 文件中
$ go install example.com/user/hello
go: finding module for package github.com/google/go-cmp/cmp
go: downloading github.com/google/go-cmp v0.4.0
go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.4.0
$ hello
Hello, Go!
  string(
- 	"Hello World",
+ 	"Hello Go",
  )
$ cat go.mod
module example.com/user/hello

go 1.14

require github.com/google/go-cmp v0.4.0
$
  • module 依赖会自动下载到 pkg/mod 文件夹下,可以通过 go clean -modcache 来删除下载的 module
$ go clean -modcache
$

Testing

  • testinggo test
  • 测试文件以 _test.go 结尾,里面有一个函数 TestXXX,其签名为 func(t *testing.T)
  • 假如函数调用了 t.Errort.Fail ,说明测试失败
  • 创建 $HOME/hello/morestrings/reverse_test.go
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
PASS
ok  	example.com/user/morestrings 0.165s
$
posted @ 2020-08-19 19:59  winechord  阅读(95)  评论(0编辑  收藏  举报