本文會演示簡單的Go軟件包的開發過程,並介紹了go
命令行工具,這是咱們獲取,構建和安裝Go軟件包和命令的標準方法。git
go工具要求你以特定方式組織代碼。咱們會介紹Go安裝啓動和運行的最簡單方法,必定要仔細閱讀啊。程序員
與其餘編程語言不一樣的是,在其餘編程語言裏每一個項目都有本身的工做區,而且工做區都與版本控制系統緊密相關。github
工做區是一個目錄層級,這個目錄層級在頂層有兩個目錄:golang
src
目錄,存放源代碼文件。shell
bin
目錄,存放可執行二進制文件。編程
go
命令工具會把src
中的Go 文件構建生成二進制文件放在bin
目錄中。緩存
src
子目錄一般包含用 git 管理的多個代碼倉庫,他們對應一個或多個Go 包的開發源碼。bash
一個典型的工做區中會包含多個源碼倉庫,對應多個可執行命令源碼和包源碼。大多數 Go 程序員會把他們的Go 源碼和全部依賴的包都放在單一的工做區中。框架
下面的例子可讓你更好的瞭解Go 的工做區大概的樣子:編程語言
bin/
hello # 可執行命令文件
outyet # 可執行命令文件
src/
github.com/golang/example/
.git/
hello/
hello.go # 命令文件源碼
outyet/
main.go # 命令文件源碼
main_test.go # 測試文件
stringutil/
reverse.go # package源碼
reverse_test.go # 測試文件
golang.org/x/image/
.git/
bmp/
reader.go # package 源碼
writer.go # package 源碼
......
複製代碼
上面的目錄樹展現了工做區中的兩個代碼倉庫(example 和 image)。example 倉庫中包含兩個命令hello 和 outyet(hello 和 outyet 目錄中存放的就是兩個命令的源碼)一個被用做庫的 package - stirngutil
。image倉庫中包含一個bmp
包。
注意:不能使用符號連接(軟鏈 ln -s)將文件連接到工做區中。
執行命令和庫是從不一樣類的源碼包構建出來的,這個以後的部分會進行說明。
GOPATH
環境變量指定工做區的位置。它缺省爲用戶目錄中名爲go的目錄,所以在Linux上爲$HOME/go
,在Windows上一般爲C:\Users\YourName\Go
。
若是想在其餘位置放置工做區,則須要將GOPATH
設置爲該目錄的路徑。請注意,GOPATH不得與GO安裝路徑相同。
命令go env GOPATH
打印當前有效的GOPATH
;若是環境變量未設置,它將打印默認位置。爲方便起見,能夠請將工做區的bin
子目錄添加到系統環境變量$PATH
中
$ export PATH=$PATH:$(go env GOPATH)/bin
複製代碼
同時也把GOPATH
設置成系統的環境變量:
$ export GOPATH=$(go env GOPATH)
複製代碼
一個***導入路徑***是用來惟一標識包的字符串,包的導入路徑和他在工做區中的位置相對應。標準庫中的包具備較短的導入路徑,如「fmt」和「net/http」。對於您本身的軟件包,你必須選擇一個不太可能與未來添加到標準庫或其餘外部庫中的內容衝突的基本路徑。
若是你將代碼保存在某個源代碼庫中,那麼應該使用該源代碼庫的根目錄做爲你的基本路徑。例如,若是你在github.com上有一個GitHub賬戶user,你建立的倉庫都會以 github.com/user 爲前綴,那麼github.com/user
這應該是你的基本路徑。
請注意,在構建代碼以前,你不須要將代碼發佈到遠程存儲庫。就像有一天會發布代碼同樣來組織代碼,這是一個好習慣。實際上,您能夠選擇任意路徑名,只要它是惟一的。
咱們將使用github.com/user
做爲基本路徑。在工做區內建立一個保存源代碼的目錄:
$ mkdir -p $GOPATH/src/github.com/user
複製代碼
要編譯並運行一個簡單的程序,首先選擇一個軟件包路徑(咱們將使用github.com/user/hello),並在您的工做區內建立一個相應的軟件包目錄:
$ mkdir $GOPATH/src/github.com/user/hello
複製代碼
接下來,在該目錄中建立一個名爲hello.go的文件,添加如下代碼:
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
複製代碼
如今,你可使用go工具構建和安裝該程序了:
$ go install github.com/user/hello
複製代碼
你能夠從系統上的任何位置運行此命令。go命令工具經過在GOPATH
指定的工做區內查找github.com/user/hello
包來查找源代碼。若是從軟件包目錄運行go Install
,能夠省略軟件包路徑:
$ cd $GOPATH/src/github.com/user/hello
$ go install
複製代碼
go install
構建hello命令,生成一個可執行的二進制文件。而後,它將該二進制文件做爲hello(在Windows下爲hello.exe)安裝到工做區的bin目錄中,hello 可執行命令的位置爲 $GOPATH/bin/hello
。
Go工具僅在發生錯誤時打印輸出,所以若是這些命令沒有產生輸出,則表明它們已成功執行。
如今,你能夠經過在命令行中鍵入程序的完整路徑來運行該程序:
$ $GOPATH/bin/hello
Hello, world.
複製代碼
因爲您已將$GOPATH/bin
添加到路徑中,所以只需鍵入二進制文件的名字:
$ hello
Hello, world.
複製代碼
讓咱們編寫一個庫並在上面寫的hello程序中使用它。
一樣,第一步是選擇軟件包路徑(咱們將使用github.com/user/stringutil)並建立軟件包目錄:
$ mkdir $GOPATH/src/github.com/user/stringutil
複製代碼
接下來在目錄中建立reverse.go
文件並添加以下代碼:
// stringutil包 存放關於字符串的工具函數
package stringutil
// Reverse 將參數中的字符串反轉後的字符串
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 build
不會產生輸出文件。相反,它將編譯後的包保存在本地構建緩存中。
在確認stringutil
包構建能夠正確以後,修改原始的hello.go
(位於$GOPATH/src/github.com/user/hello中)以使用它:
package main
import (
"fmt"
"github.com/user/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("!oG ,olleH"))
}
複製代碼
再次編譯安裝 hello 程序後運行他,能夠看到輸出中的字符串已經被反轉了。
$ hello
Hello, Go!
複製代碼
通過上面幾步後你的工做區如今應該看起來像下面這樣:
bin/
hello
src/
github.com/user/
hello/
hello.go
stringutil/
reverse.go
複製代碼
go 源碼文件中的第一行語句必須是:
package name
複製代碼
其中,name是用於導入的包的默認名稱。(包中的全部文件必須使用相同的名稱)
go的慣例是包名是導入路徑的最後一個元素:做爲「crypto/rot13」導入的包它的包名爲rot13
。
生成可執行命令的源碼文件必須以main
做爲包名。
go 中不要求連接到單個二進制文件的全部包的包名都是惟一的,只要求導入路徑(它們的完整文件名)是惟一的。
go有一個由go測試命令和測試包組成的輕量級測試框架。你能夠經過建立一個名字以_test.go
結尾的文件來編寫測試,該文件包含名爲TestXXX的函數,簽名函數爲func(t*testing.T)
。測試框架運行每一個這樣的函數;若是函數調用失敗函數,如t.Error或t.Fail,則認爲測試失敗。
經過建立包含如下go代碼的文件$GOPATH/src/github.com/user/stringutil/reverse_test.go
,將測試添加到strangutil
包。
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 github.com/user/stringutil
ok github.com/user/stringutil 0.165s
複製代碼
導入路徑能夠描述如何從版本控制系統(如Git)獲取包源代碼。Go工具使用此屬性自動從遠程倉庫中獲取包。例如,本文檔中描述的示例也保存在GitHub 以github.com/golang/example託管的Git存儲庫中。若是將代碼倉庫的URL包含在軟件包的導入路徑中,go將會使用go get`自動獲取、構建和安裝它:
$ go get github.com/golang/example/hello
$ $GOPATH/bin/hello
Hello, Go examples!
複製代碼
若是工做區中沒有指定的包,go get
將把它放在$GOPATH
指定的工做區中。(若是軟件包已經存在,go get
將跳過遠程獲取,其行爲變得與go install
相同。)。
發出上述go get
命令後,工做區目錄樹如今應該以下所示:
bin/
hello
src/
github.com/golang/example/
.git/
hello/
hello.go
stringutil/
reverse.go
reverse_test.go
github.com/user/
hello/
hello.go
stringutil/
reverse.go
reverse_test.go
複製代碼
託管在GitHub上的hello命令依賴於同一倉庫中的stringutil
包。hello.go
文件中的導入使用相同的導入路徑約定,所以go get
命令也可以定位和安裝依賴包。
import "github.com/golang/example/stringutil"
複製代碼