本文演示了一個簡單的Go語言包的開發,以及 go tool
命令的使用,包含:獲取、構建、安裝Go包和命令的標準方法。php
go tool
要求用特別的方式來組織你的Go代碼。仔細閱讀本文,它解釋了啓動和運行Go安裝的最簡單方法。html
請注意,這與其餘編程環境不一樣,在這些環境中,每一個項目都有一個單獨的工做區,工做區與版本控制倉庫緊密相關。git
工做空間是一個目錄層次結構,其根目錄有兩個目錄:程序員
src
用於存放Go原文件bin
存放可執行的命令go工具構建二進制文件並將其安裝到 bin
目錄。github
src
子目錄一般包含多個版本控制的倉庫(例如Git),用於跟蹤一個或多個源包的開發。golang
在實踐中,工做區應該是什麼樣子呢? 下面給出一個例子:編程
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) ...
上面的這個樹型結構展現出一個工做區包含了2個倉庫(example
和 image
)。example
倉庫包含了2個命令(hello
和 outyet
)和一個庫(stringutil
)。image
倉庫包含了 bmp
包和 一些其餘的包。vim
一般工做區會包含不少的源倉庫(包含須要多和命令)。大多數的Go開發者都會把他們的源代碼和依賴存放在一個工做區。windows
命令和庫是從不一樣類型的源包構建的。咱們稍後會討論這種區別。緩存
GOPATH
環境變量用來指定工做區的位置。默認是用戶主目錄的 go
目錄,如在Linux和macOS上是 $HOME/go
, 在Windows上是 C:\Users\YourName\go
。
go env GOPATH
命令會打印出當前有效的 GOPATH
; 若是環境變量沒有被設置會打印出默認的位置。
爲方便起見,將工做空間的 bin
子目錄添加到 PATH
:
$ export PATH=$PATH:$(go env GOPATH)/bin
爲簡潔起見,本文檔其他部分中的腳本使用 $GOPATH
而不是 $(go env GOPATH)
。即
$ export PATH=$PATH:$GOPATH/bin
而若是尚未設置 $GOPATH
就運行寫好的腳本,你須要替換爲 $HOME/go
, 不然須要執行:
$ export GOPATH=$(go env GOPATH)
要學習更多關於gopath環境變量,可使用查看幫助 go help gopath
要使用自定義的工做區,能夠查看 https://golang.org/wiki/SettingGOPATH
導入路徑(import path)是惟一標識包的字符串。包的導入路徑對應於其在工做空間內或遠程倉庫中的位置(以下所述)。
標準庫中的包具備簡短的導入路徑,例如 fmt
和 net/http
。對於咱們本身開發的包您必須選擇一個基本路徑,該路徑不太可能與未來添加到標準庫或其餘外部庫中發生衝突。
若是將代碼保存在某個源倉庫中,則應使用該源倉庫的根做爲基本路徑。例如,若是你在 github.com/user
上有一個GitHub賬戶,那麼這應該是你的基本路徑。
請注意,在構建代碼以前,無需將代碼發佈到遠程倉庫。組織代碼只是一個好習慣,好像有一天你會發布它同樣。實際上,你能夠選擇任意路徑名稱,只要它對標準庫和更大的Go生態系統是惟一的。
咱們將使用 github.com/user
做爲咱們的基本路徑。在工做區內建立一個目錄,用於保存源代碼:
$ mkdir -p $GOPATH/src/github.com/user
要編譯和運行一個簡單的程序,首先要選擇一個包路徑(咱們會使用 github.com/user/hello
),而後在工做區裏建立一個相應的包目錄:
$ mkdir $GOPATH/src/github.com/user/hello
接下來,在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
該命令會生成一個 hello
命令,生成一個可執行的二進制文件。同時安裝到工做區目錄下的 bin
目錄,生成的可執行文件是 hello
(若是是windows則是 hello.exe)。
在本例子中是 $GOPATH/bin/hello
, 也就是 $HOME/go/bin/hello
。
當有錯誤發生的時候,go工具僅會打印除錯誤,因此若是沒有任何輸出的時候說明已經執行成功。
能夠經過全路徑來運行:
$ $GOPATH/bin/hello Hello, world.
若是已經把 $GOPATH/bin
加入到了 PATH
, 能夠直接輸入二進制文件名:
$ hello Hello, world.
若是你正在使用一個版本控制系統,好比Git,如今是時候來初始化來生成一個倉庫(repository),而後添加文件,作第一次提交。
固然這一步是可選的,不必定非要使用版本控制系統來寫Go代碼
$ cd $GOPATH/src/github.com/user/hello $ git init Initialized empty Git repository in /home/user/work/src/github.com/user/hello/.git/ $ git add hello.go $ git commit -m "initial commit" [master (root-commit) 0b4507d] initial commit 1 file changed, 1 insertion(+) create mode 100644 hello.go $ git push origin master
咱們再來寫一個庫,並在 hello
程序中使用。
首先,第一步肯定好包路徑,咱們使用 github.com/user/stringutil
, 建立包目錄
$ 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
若是已經在 github.com/user/stringutil
目錄裏,則直接執行:
$ go build
固然該命令不會生成文件,而是把編譯好的包放到了本地的構建(build)緩存裏。
確實 stringutil
包被編譯後, 修改 hello.go
:
vim $GOPATH/src/github.com/user/hello
修改後的:
package main import ( "fmt" "github.com/user/stringutil" ) func main() { fmt.Println(stringutil.Reverse("!oG ,olleH")) }
再次安裝
$ go install github.com/user/hello
執行:
$ hello Hello, Go!
經過上面的一些步驟後,如今咱們的結構是這樣子的:
bin/ hello # command executable src/ github.com/user/ hello/ hello.go # command source stringutil/ reverse.go # package source
在Go原文件中第一個使用的語句必須是
package name
其中 name
就是包的默認名稱。一個包中的全部文件必須使用相同的包名。
Go的約定是包名稱是導入路徑的最後一個元素,例如導入的包 crypto/rot13
, 包名就是 rot13
若是是可執行的文件,包名必須使用 main
。
不強制要求全部的包名都是惟一的,可是要求導入的路徑必須是惟一的(全路徑文件名)。
更多關於go的命名規範能夠查看 Effective Go
Go提供了一個由 go test
和 testing
包組成的測試框架。
經過建立一個以 _test.go
結尾的文件,裏面寫有以 TestXXX
開頭的函數。測試框架會運行每個這樣的函數,若是函數調用了一個失敗的函數,如 t.Error
或 t.Error
, 那麼測試就算不經過。
經過添加一個測試文件到 stringutil
包中,
$ vim $GOPATH/src/github.com/user/stringutil/reverse_test.go
添加以下代碼:
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
若是當前是在 go test github.com/user/stringutil
目錄中,則直接執行:
$ go test ok github.com/user/stringutil 0.165s
更多細節能夠運行 go run test 和 查看 測試包文檔
導入路徑能夠描述如何使用諸如Git之類的版本控制系統來獲取包源代碼。go工具使用此屬性自動從遠程倉庫獲取包。例如,本文檔中描述的示例也保存在GitHub github.com/golang/example
上託管的Git倉庫中。若是你在包的導入路徑中包含倉庫URL,那麼go將自動獲取,構建和安裝它:
$ go get github.com/golang/example/hello $ $GOPATH/bin/hello Hello, Go examples!
若是指定的包不在工做區, go get
將會經過 GOPATH
把它放到指定的工做區,若是包已經存在, go get
會跳過遠程獲取,其行爲與 go install
相同。
上面 go get
以後的目錄結構以下:
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
在GitHub上託管的 hello
命令取決於同一倉庫中的 stringutil
包。 hello.go
文件中的導入使用相同的導入路徑約定,所以 go get
命令也可以找到並安裝依賴包。
import "github.com/golang/example/stringutil"
此約定是使你的Go包可供其餘人使用的最簡單方法。
Go Wiki和godoc.org提供了外部Go項目的列表。
有關使用go工具使用遠程倉庫的更多信息, 能夠查看 go help importpath
原文地址: https://phpcasts.org/topics/47