本文是 How to Write Go Code 的學習筆記。通過示範介紹了Go 語言的開發過程和 go
工具的使用。
1. 代碼結構
go 語言特點
- go 開發者通常將所有代碼組織在一個工作空間下
- 一個工作空間包含多個版本控制庫(git)
- 一個版本控制庫中包含一個或多個應用包
- 一個包由多個go 源代碼文件組成
1.1 工作空間
工作空間包含三個子目錄
src
包含所有源代碼文件pkg
包含所有包對象,庫依賴文件等bin
包含所有可執行文件
go
工具編譯源碼產生的結果,會存放到 pkg 和 bin 目錄。src
目錄一般包含多個版本控制庫,以追蹤多個源碼庫的開發.
一個典型的 go 工作空間如下:
bin/
hello # command executable
outyet # command executable
pkg/
linux_amd64/
github.com/golang/example/
stringutil.a # package object
src/
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
golang.org/x/image/
.git/ # Git repository metadata
bmp/
reader.go # package source
writer.go # package source
示例包含兩個版本庫(example 和 image),可執行目錄和依賴庫目錄。
1.2 GOPATH 環境變量
GOPATH 環境變量指定 go 工作空間的位置,在開發go 代碼前指定。
一般設置在當前用戶目錄下,如下所示:
$ mkdir $HOME/work # 創建工作空間目錄
export GOPATH=$HOME/work # 指定go 工作空間
export PATH=$PATH:$GOPATH/bin # 將可執行文件目錄加入環境變量,方便使用
1.3 導入路徑
導入路徑是一個包的唯一標識,指定包所在的位置。
導入標準庫的包時,指定短導入路徑,例如 “fmt”, “net/http” 等
導入自定義包時,根據 $GOPATH
相對路徑引入
1.4 第一個程序
go 源碼放在 $GOPATH/src
路徑下。
新建 $GOPATH/src/go_note/src/hello/hello.go
文件,內容如下:
// go "hello world" 示例
package main
import "fmt"
func main() {
fmt.Printf("Hello, world.\n")
}
通過 go install
命令編譯安裝程序:
$ go install go_note/src/hello
go 會找到 $GOPATH/src/go_note/src/hello/
目錄下的源碼文件,編譯完成將編譯結果存放在 $GOPATH/bin
目錄下。
執行該程序
$ $GOPATH/bin/hello
Hello, world.
1.5 第一個庫
新建 $GOPATH/src/go_note/src/stringutil/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)
}
使用 go build
命令進行編譯檢查
$ go build go_note/src/stringutil
go build
不會輸出任何文件,通過 go install
將包對象放入 pkg
目錄
確認包編譯檢查正確後,在 hello.go
文件中使用該包
package main
import (
"fmt"
"go_note/src/stringutil"
)
func main() {
// 輸出字符串
fmt.Printf("hello, world\n")
// 反轉字符串
fmt.Printf(stringutil.Reverse("\nhello, world"))
}
重新編譯安裝 hello
$ go install go_note/src/hello
go install
自動引入 stringutil
庫
執行編譯後的 hello
$ $GOPATH/bin/hello
hello, world
dlrow ,olleh
此時工作空間結構如下:
bin/
hello # command executable
pkg/
darwin_amd64/ # this will reflect your OS and architecture
go_note/src/
stringutil.a # package object
src/
go_note/src/
hello/
hello.go # command source
stringutil/
reverse.go # package source
1.6 包名
go 代碼的第一條語句是包名聲明語句。
package name
導入包時,通過包名指定需要導入的包
2. 測試
go 通過 go test
命令和測試包組成了一個輕量測試框架。
創建以 _test.go
結尾,函數名以 TestXXX
形式組成並且包含 func (t *testing.T)
結構的代碼文件,測試框架會逐個運行這些函數,如果函數拋出 t.Error
或者 t.Fail
異常,就表示測試不通過。
新建測試文件 $GOPATH/src/go_note/src/stringutil/reverse_test.go
,內容如下:
// reverse library 的測試包
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)
}
}
}
執行測試工具 go test
$ go test go_note/src/stringutil
ok go_note/src/stringutil 0.006s
3. 遠程包
導入路徑描述如何從版本控制系統中過去代碼,go 工具通過這個屬性,可以獲取遠程包
go get
獲取 https://github.com/golang/example
代碼,編譯並且安裝相應文件
$ go get github.com/golang/example/hello
$ $GOPATH/bin/hello
Hello, Go examples!