如何编写Go代码
簡介
本文演示了一個簡單的Go語言包的開發,以及 go tool 命令的使用,包含:獲取、構建、安裝Go包和命令的標準方法。
go tool 要求用特別的方式來組織你的Go代碼。仔細閱讀本文,它解釋了啟動和運行Go安裝的最簡單方法。
代碼組織
概述
- 程序員通常會將所有Go代碼保存在一個工作區中
- 工作空間包含許多版本控制的倉庫(repo)(例如,由Git管理的)
- 每個倉庫包含一個或多個包
- 每個包由一個目錄中的一個或多個Go源文件組成
- 包目錄的路徑確定其導入路徑
請注意,這與其他編程環境不同,在這些環境中,每個項目都有一個單獨的工作區,工作區與版本控制倉庫緊密相關。
工作區
工作空間是一個目錄層次結構,其根目錄有兩個目錄:
- src 用于存放Go原文件
- bin 存放可執行的命令
go工具構建二進制文件并將其安裝到 bin 目錄。
src 子目錄通常包含多個版本控制的倉庫(例如Git),用于跟蹤一個或多個源包的開發。
在實踐中,工作區應該是什么樣子呢? 下面給出一個例子:
bin/hello # command executableoutyet # command executable src/github.com/golang/example/.git/ # Git repository metadatahello/hello.go # command sourceoutyet/main.go # command sourcemain_test.go # test sourcestringutil/reverse.go # package sourcereverse_test.go # test sourcegolang.org/x/image/.git/ # Git repository metadatabmp/reader.go # package sourcewriter.go # package source... (many more repositories and packages omitted) ...上面的這個樹型結構展示出一個工作區包含了2個倉庫(example 和 image)。example 倉庫包含了2個命令(hello 和 outyet)和一個庫(stringutil)。image 倉庫包含了 bmp 包和 一些其他的包。
通常工作區會包含很多的源倉庫(包含需要多和命令)。大多數的Go開發者都會把他們的源代碼和依賴存放在一個工作區。
命令和庫是從不同類型的源包構建的。我們稍后會討論這種區別。
GOPATH 環境變量
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你的第一個Go程序
要編譯和運行一個簡單的程序,首先要選擇一個包路徑(我們會使用 github.com/user/hello),然后在工作區里創建一個相應的包目錄:
$ mkdir $GOPATH/src/github.com/user/hello接下來,在hello目錄里創建一個 hello.go 文件,寫入以下內容:
package mainimport "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 commit1 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:
修改后的:
package mainimport ("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 sourcestringutil/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 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:
$ 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 metadatahello/hello.go # command sourcestringutil/reverse.go # package sourcereverse_test.go # test sourcegithub.com/user/hello/hello.go # command sourcestringutil/reverse.go # package sourcereverse_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總結
- 上一篇: JS(JavaScript)的初了解6(
- 下一篇: spring coud feign