這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
1:程式碼群組織
go開發人員通常將所有的go代碼放在一個單獨的workspace中。一個workspace可以包含多個版本控制庫(比如git),每一個庫包含若干package,每個package就是包含一個或多個go源碼檔案的目錄;package目錄的路徑決定他的引用路徑;
workspace下通常有3個子目錄:src包含go源碼檔案;pkg包含package對象;bin包含可執行程式。go編譯時間,構建src中的go源碼,並將編譯後的二進位檔案安裝到pkg和bin中;
下面是一個workspace的例子:
bin/ hello # command executable outyet # command executablepkg/ linux_amd64/ github.com/golang/example/ stringutil.a # package objectsrc/ 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 ... (many more repositories and packages omitted) ...
上面的workspace中包含兩個版本庫:example和image。example庫包含2個可執行程式:hello和outyet,一個庫檔案stringutil。image庫包含bmp和其他package等。
2:GOPATH環境變數
環境變數GOPATH指明了workspace的位置。預設情況下,該環境變數的值是home目錄下的名為go的子目錄,比如Unix下的$HOME/go,Windows下的C:\Users\YourName\go。
通過設定GOPATH來指明workspace的具體位置。注意GOPATH不能設定為和GO的安裝目錄一樣。
“go env GOPATH”命令可以列印出GOPATH的當前值。
3:引用路徑(import path)
引用路徑用於唯一標識一個package。package的引用路徑對應該packge相對於workspace中的位置,或者是一個遠程庫的地址。
標準庫中的package引用路徑都是像”fmt”和”net/http”這樣的短路徑。對於自己定義的package,必須選擇一個不會與標準庫發生衝突的基路徑。
比如,以github.com/user為基路徑,需要在workspace中建立對應的目錄:
mkdir -p $GOPATH/src/github.com/user
4:第一個程式
首先是確定package路徑,這裡使用的路徑是github.com/user/hello,在workspace中建立對應的目錄:
mkdir $GOPATH/src/github.com/user/hello
然後在上面的目錄中建立源碼檔案hello.go,其內容如下:
package mainimport "fmt"func main() { fmt.Printf("Hello, world.\n")}
接下來就可以編譯、構建並安裝該package了:
go install github.com/user/hello
上面的命令可以在系統內任意位置執行。go編譯器可以通過GOPATH環境變數得到workspace的路徑,進而在其中的github.com/user/hello這個package中找到源碼。
go install命令構建hello,產生一個可執行檔,並將該檔案安裝到workspace中的bin目錄下。運行該程式如下:
$GOPATH/bin/helloHello, world.
5:第一個庫
首先是確定package路徑,並且在workspace中建立對應的目錄:
mkdir $GOPATH/src/github.com/user/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 github.com/user/stringutil
上面的命令不會產生輸出檔案。必須使用go install命令,才能在pkg目錄下產生package對象。
接下來,修改hello.go檔案如下:
package mainimport ( "fmt" "github.com/user/stringutil")func main() { fmt.Printf(stringutil.Reverse("!oG ,olleH"))}
當go編譯安裝package或二進位檔案時,它也會安裝它的依賴。所以,當安裝hello時,它所依賴的stringutil也會被自動安裝:
go install github.com/user/hello
運行新程式,結果如下:
helloHello, Go!
現在,workspace的內容如下:
bin/ hello # command executablepkg/ linux_amd64/ # this will reflect your OS and architecture github.com/user/ stringutil.a # package objectsrc/ github.com/user/ hello/ hello.go # command source stringutil/ reverse.go # package source
go install命令會將stringutil.a檔案安裝到pkg/linux_amd64目錄中,對應於源碼的子目錄下。因此,後續編譯時間,編譯器可以找到該package檔案,避免不必要的重編譯。”linux_amd64”主要是用於跨平台編譯時間,用於標識作業系統和CPU架構。
go可執行程式是靜態連結的,運行go程式時,package對象檔案不是必須存在的。
6:Package名
go源碼檔案中的第一條聲明語句必須是:package name
其中的name就是package的引用名,同一個package中的源碼檔案必須使用相同的名字。
GO的慣例是package名就是引用路徑的最後一個元素,比如引用路徑為"crypto/rot13"的package,其名為rot13。
可執行程式必須以main作為package名。
多個package連結成一個二進位檔案時,這些package的名字不一定必須是獨一無二的,只要他們的引用路徑不同即可。
7:測試
go具有一個輕量級的測試架構,該測試架構套件含go test命令,以及testing package。
編寫測試代碼時,源碼檔案名稱需要以”_test.go”結尾,函數的形式是:func TestXXX(t *testing.T)。
測試架構運行每個測試函數,如果函數中調用到了t.Error或t.Fail,表示測試失敗。
比如,如果需要測試stringutil這個package,則可以建立檔案$GOPATH/src/github.com/user/stringutil/reverse_test.go,該檔案內容如下:
package stringutilimport "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 github.com/user/stringutilok github.com/user/stringutil 0.165s
或者,如果當前就在package目錄中,可以直接運行go test命令:
go testok github.com/user/stringutil 0.165s
8:遠端package
package的引用路徑還可以用於描述如何從版本控制系統如git或mercurial中擷取源碼。go編譯器可以使用該特性從遠端庫中擷取package。
比如上面例子中的代碼也存在於GIT庫:github.com/golang/example中。如果在源碼中,引用路徑使用的是該URL地址,則可以使用go get命令,該命令會從遠端拉取package,並進行編譯安裝:
go get github.com/golang/example/hello$GOPATH/bin/helloHello, Go examples!
如果package不在當前的workspace中,go get將會將其放置到GOPATH指定的workspace下,如果該package已經存在了,則go get會省略遠端拉取的過程,剩下的動作與go install一樣。
運行完go get命令後,workspace目錄階層如下:
bin/ hello # command executablepkg/ linux_amd64/ github.com/golang/example/ stringutil.a # package object github.com/user/ stringutil.a # package objectsrc/ 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
可以重新編輯github.com/user/hello/hello.go檔案,將
import "stringutil"
改為
import "github.com/golang/example/stringutil"
這樣,執行go get github.com/user/hello時,就會首先從遠端下載stringutil這個package,然後再編譯安裝hello。
https://golang.org/doc/code.html