預(yù)覽
- Go程序員通常讓所有的Go代碼在一個單獨(dú)的工作空間(workspace).
- 一個工作空間包含很多版本控制倉庫(比如虑润,通過git管理)
- 每個倉庫包含一個或者多個包(packages).
- 每個包由單獨(dú)的目錄下的Go源文件組成.
- 包的目錄路徑?jīng)Q定他的導(dǎo)入路徑
注意這是和其他編程環(huán)境不同的地方:每個項(xiàng)目都有單獨(dú)的工作空間,并且工作空間與版本控制倉庫緊密綁定
工作空間
工作根目錄有兩個目錄:
- src包含夠源文件
- bin包含可執(zhí)行命令
go tool
構(gòu)建并安裝binaries到bin目錄
src
子目錄一般包含多個版本控制倉庫(比如Git或者M(jìn)ercurial)追蹤一個或多個源包的開發(fā)搅窿。
下面展示工作空間的結(jié)構(gòu):
bin/
hello # command executable
outyet # command executable
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
... (many more repositories and packages omitted) ...</pre>
上面的樹顯示工作空間包含兩個倉庫(example
和image
)违帆。example
倉庫包含兩個命令(hello
和outyet
)和一把庫(stringutil
). image
倉庫包含bmp
包和其他的一些內(nèi)容
經(jīng)典的工作空間包含多個源倉庫律杠,源倉庫包含多個包和命令簸喂。大多數(shù)的Go程序員將所有的Go源代碼和依賴放在一個單獨(dú)的工作空間。
注意侵续,不應(yīng)該使用symbolic links關(guān)聯(lián)文件或者目錄到工作空間倔丈。
GOPATH環(huán)境變量
GOPATH環(huán)境變量指定工作空間的位置。默認(rèn)是在home目錄里的go目錄状蜗,比如Unix的$HOME/go
需五,Windows的%USERPROFILE%\go
(通常是C:\Users\YourName\go
)。
如果想在不同的地方轧坎,可以使用set GOPATH
指定目錄的路徑宏邮。(另一種通用的設(shè)置是GOPATH=$HOME).注意GOPATH一定不能是Go的安裝目錄。
go env
命令打印當(dāng)前有效的GOPATH,如果沒有設(shè)置則打印默認(rèn)的位置缸血。
為了方便蜜氨,添加工作空間的bin目錄到你的路徑:
$ export PATH=$PATH:$(go env GOPATH)/bin
為了簡短,接下來的文檔使用(go env GOPATH)捎泻。
導(dǎo)入路徑(Import paths)
import path
是唯一的字符串表示包飒炎。包的導(dǎo)入路徑對應(yīng)工作空間里它的位置或者遠(yuǎn)程倉庫位置。
標(biāo)準(zhǔn)庫里的包具有簡短的導(dǎo)入路徑笆豁,比如fmt
和net/http
郎汪。對于你自己的包,指定的路徑不能與標(biāo)準(zhǔn)庫里的包或者其他內(nèi)部包沖突闯狱。
如果你將代碼保存在源文件倉庫煞赢,那么應(yīng)該使用源倉庫的根目錄作為你的基礎(chǔ)路徑。比如哄孤,如果你有Github
賬號照筑,那么github.com/{user}
就是你的基本路徑。
注意不要再你能構(gòu)建之前推送代碼到遠(yuǎn)程倉庫瘦陈。
我們將使用github.com/{user}
作為你的基礎(chǔ)路徑朦肘。在工作空間下創(chuàng)建一個目錄保存源代碼:
$ mkdir -p $GOPATH/src/github.com/user
第一個程序
要編譯和運(yùn)行一個簡單的程序,先選擇一個包路徑(我們先用github.com/user/hello)并且在工作空間創(chuàng)建相應(yīng)的包目錄:
$ mkdir $GOPATH/src/github.com/user/hello
接下來双饥,在這個目錄下創(chuàng)建一個名為hello.go
的文件,包含如下代碼:
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
現(xiàn)在就可以構(gòu)建并安裝程序了:
$ go install github.com/user/hello
現(xiàn)在你就可以在你的系統(tǒng)里運(yùn)行這個命令了弟断。go tool
通過GOPATH指定的工作空間查找github.com/user/hello
包的源代碼
如果已經(jīng)在包目錄里咏花,就可以省略掉包路徑
$ cd $GOPATH/src/github.com/user/hello
$ go install
這個命令構(gòu)建hello
命令,產(chǎn)生一個可執(zhí)行的binary。然后安裝這個binary到工作空間下的bin目錄昏翰,也就是$HOME/go/bin/hello
go tool
只會在有錯誤的時候打印輸出苍匆,所以如果沒有內(nèi)容產(chǎn)生,表示執(zhí)行成功棚菊。
現(xiàn)在可以通過全路徑運(yùn)行程序
$ $GOPATH/bin/hello
Hello, world.
第一個庫
現(xiàn)在我們編寫一個library并且在hello
程序里使用浸踩。
同樣,第一步先選擇一個包路徑(我們使用github.com/user/stringutil)先统求,創(chuàng)建包路徑
$ mkdir $GOPATH/src/github.com/user/stringutil
然后創(chuàng)建一個命為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)
}
現(xiàn)在检碗,使用go build
測試包編譯:
$ go build github.com/user/stringutil
如果已經(jīng)在包源目錄下,只需要:
go build
這不會產(chǎn)生輸出文件码邻。而是將編譯完的包保存到本地構(gòu)建緩存里折剃。
現(xiàn)在修改hello.go
來使用它:
package main
import (
"fmt"
"github.com/user/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("!oG, olleH"))
}
install hello
程序
$ go install github.com/user/hello
這一頓操作后,工作空間應(yīng)該變成了:
bin/
hello # command executable
src/
github.com/user/
hello/
hello.go # command source
stringutil/
reverse.go # package source
Package names
Go源文件里的第一行一定是:
package name
其中name是包的默認(rèn)名稱像屋。
(包中的所有文件必須使用相同的名稱怕犁。)
Go的約定是報名是導(dǎo)入路徑最后一個節(jié)點(diǎn):crypto/rot13
的包名是rot13
可執(zhí)行命令的包名必須是package main
。
不要求包名稱在鏈接到單個二進(jìn)制文件的所有包中都是唯一的己莺,只要導(dǎo)入路徑(它們的完整文件名)是唯一的奏甫。
測試
Go有一個由go test
命令和測試包組成的輕量級測試框架。
創(chuàng)建一個用_test.go
結(jié)尾的文件凌受,里面的方法命名為TestXXX
阵子。測試框架會運(yùn)行每個方法;如果方法調(diào)用失敗方法比如t.Error
或者t.Fail
胁艰,測試就被認(rèn)為失敗了款筑。
創(chuàng)建一個$GOPATH/src/github.com/user/stringutil/reverse_test.go
文件測試stringutil
:
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 github.com/user/stringutil
ok github.com/user/stringutil 0.165s
遠(yuǎn)程包
導(dǎo)入路徑可以描述如何使用諸如Git或Mercurial之類的修訂控制系統(tǒng)來獲取包源代碼。go tool使用該屬性自動從遠(yuǎn)程倉庫拉去包腾么。比如奈梳,本文檔里的實(shí)例就保存在github.com/golang/example
。如果你在包的導(dǎo)入路徑引入遠(yuǎn)程URL, go get將會自動獲取解虱,構(gòu)建并且安裝它:
$ go get github.com/golang/example/hello
$ $GOPATH/bin/hello
Hello, Go examples!
如果工作空間不存在指定的包攘须,go get
會將它放在GOPATH指定的第一個工作空間內(nèi)。(如果包存在殴泰,go get
會跳過遠(yuǎn)程獲取于宙,就和go install
的行為一樣了)
經(jīng)過上面的操作后,工作目錄結(jié)構(gòu)將會變?yōu)椋?/p>
bin/
hello # command executable
src/
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
Gihub上托管的hello
命令依賴同一倉庫下的stringutil
包悍汛。hello.go
文件里的imports使用相同的導(dǎo)入路徑規(guī)范捞魁,所以go get命令可以定位并且安裝起來的包:
import "github.com/golang/exmaple/stringutil"
規(guī)范是最簡單的方式讓你的Go包可以對其他的可用