本文是 How to Write Go Code 的學(xué)習(xí)筆記书在。通過示范介紹了Go 語言的開發(fā)過程和 go
工具的使用灼捂。
1. 代碼結(jié)構(gòu)
go 語言特點(diǎn)
- go 開發(fā)者通常將所有代碼組織在一個(gè)工作空間下
- 一個(gè)工作空間包含多個(gè)版本控制庫(git)
- 一個(gè)版本控制庫中包含一個(gè)或多個(gè)應(yīng)用包
- 一個(gè)包由多個(gè)go 源代碼文件組成
1.1 工作空間
工作空間包含三個(gè)子目錄
-
src
包含所有源代碼文件 -
pkg
包含所有包對象双揪,庫依賴文件等 -
bin
包含所有可執(zhí)行文件
go
工具編譯源碼產(chǎn)生的結(jié)果视事,會存放到 pkg 和 bin 目錄强重。src
目錄一般包含多個(gè)版本控制庫,以追蹤多個(gè)源碼庫的開發(fā).
一個(gè)典型的 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
示例包含兩個(gè)版本庫(example 和 image)纱意,可執(zhí)行目錄和依賴庫目錄婶溯。
1.2 GOPATH 環(huán)境變量
GOPATH 環(huán)境變量指定 go 工作空間的位置,在開發(fā)go 代碼前指定偷霉。
一般設(shè)置在當(dāng)前用戶目錄下迄委,如下所示:
$ mkdir $HOME/work # 創(chuàng)建工作空間目錄
export GOPATH=$HOME/work # 指定go 工作空間
export PATH=$PATH:$GOPATH/bin # 將可執(zhí)行文件目錄加入環(huán)境變量,方便使用
1.3 導(dǎo)入路徑
導(dǎo)入路徑是一個(gè)包的唯一標(biāo)識类少,指定包所在的位置叙身。
導(dǎo)入標(biāo)準(zhǔn)庫的包時(shí),指定短導(dǎo)入路徑硫狞,例如 "fmt", "net/http" 等
導(dǎo)入自定義包時(shí)信轿,根據(jù) $GOPATH
相對路徑引入
1.4 第一個(gè)程序
go 源碼放在 $GOPATH/src
路徑下赞警。
新建 $GOPATH/src/go_note/src/hello/hello.go
文件,內(nèi)容如下:
// 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/
目錄下的源碼文件虏两,編譯完成將編譯結(jié)果存放在 $GOPATH/bin
目錄下。
執(zhí)行該程序
$ $GOPATH/bin/hello
Hello, world.
1.5 第一個(gè)庫
新建 $GOPATH/src/go_note/src/stringutil/reverse.go
庫文件世剖,內(nèi)容如下:
// 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
命令進(jìn)行編譯檢查
$ go build go_note/src/stringutil
go build
不會輸出任何文件定罢,通過 go install
將包對象放入 pkg
目錄
確認(rèn)包編譯檢查正確后,在 hello.go
文件中使用該包
package main
import (
"fmt"
"go_note/src/stringutil"
)
func main() {
// 輸出字符串
fmt.Printf("hello, world\n")
// 反轉(zhuǎn)字符串
fmt.Printf(stringutil.Reverse("\nhello, world"))
}
重新編譯安裝 hello
$ go install go_note/src/hello
go install
自動(dòng)引入 stringutil
庫
執(zhí)行編譯后的 hello
$ $GOPATH/bin/hello
hello, world
dlrow ,olleh
此時(shí)工作空間結(jié)構(gòu)如下:
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
導(dǎo)入包時(shí)祖凫,通過包名指定需要導(dǎo)入的包
2. 測試
go 通過 go test
命令和測試包組成了一個(gè)輕量測試框架。
創(chuàng)建以 _test.go
結(jié)尾酬凳,函數(shù)名以 TestXXX
形式組成并且包含 func (t *testing.T)
結(jié)構(gòu)的代碼文件惠况,測試框架會逐個(gè)運(yùn)行這些函數(shù),如果函數(shù)拋出 t.Error
或者 t.Fail
異常宁仔,就表示測試不通過稠屠。
新建測試文件 $GOPATH/src/go_note/src/stringutil/reverse_test.go
,內(nèi)容如下:
// 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)
}
}
}
執(zhí)行測試工具 go test
$ go test go_note/src/stringutil
ok go_note/src/stringutil 0.006s
3. 遠(yuǎn)程包
導(dǎo)入路徑描述如何從版本控制系統(tǒng)中過去代碼翎苫,go 工具通過這個(gè)屬性权埠,可以獲取遠(yuǎn)程包
go get
獲取 https://github.com/golang/example
代碼,編譯并且安裝相應(yīng)文件
$ go get github.com/golang/example/hello
$ $GOPATH/bin/hello
Hello, Go examples!