本文會演示簡單的Go軟件包的開發(fā)過程沛贪,并介紹了go命令行工具褒墨,這是我們獲取,構建和安裝Go軟件包和命令的標準方法橘原。
go工具要求你以特定方式組織代碼籍铁。我們會介紹Go安裝啟動和運行的最簡單方法,一定要仔細閱讀啊趾断。
組織代碼結構
概要
Go 程序員一般會將他們的源代碼存放在一個工作區(qū)中(多個項目放在一個工作區(qū))
工作區(qū)中包含許多由 git 管理的代碼倉庫(也可以是其他版本控制工具管理的)
每個代碼倉庫包含一個或者多個 Go package
每個 package 由單一目錄下的一個或多個Go 源碼文件組成
package 的目錄路徑決定了其導入路徑
與其他編程語言不同的是拒名,在其他編程語言里每個項目都有自己的工作區(qū),并且工作區(qū)都與版本控制系統(tǒng)緊密相關歼冰。
工作區(qū)
工作區(qū)是一個目錄層級靡狞,這個目錄層級在頂層有兩個目錄:
src目錄,存放源代碼文件隔嫡。
bin目錄甸怕,存放可執(zhí)行二進制文件。
go命令工具會把src中的Go 文件構建生成二進制文件放在bin目錄中腮恩。
src子目錄通常包含用 git 管理的多個代碼倉庫梢杭,他們對應一個或多個Go 包的開發(fā)源碼。
一個典型的工作區(qū)中會包含多個源碼倉庫秸滴,對應多個可執(zhí)行命令源碼和包源碼武契。大多數(shù) Go 程序員會把他們的Go 源碼和所有依賴的包都放在單一的工作區(qū)中。
下面的例子可以讓你更好的了解Go 的工作區(qū)大概的樣子:
bin/
? ? hello? ? ? ? ? ? ? ? ? ? ? ? ? # 可執(zhí)行命令文件
? ? outyet? ? ? ? ? ? ? ? ? ? ? ? # 可執(zhí)行命令文件
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 源碼
? ......
上面的目錄樹展示了工作區(qū)中的兩個代碼倉庫(example 和 image)荡含。example 倉庫中包含兩個命令hello 和 outyet(hello 和 outyet 目錄中存放的就是兩個命令的源碼)一個被用作庫的 package -stirngutil咒唆。image倉庫中包含一個bmp包。
注意:不能使用符號鏈接(軟鏈 ln -s)將文件鏈接到工作區(qū)中释液。
執(zhí)行命令和庫是從不同類的源碼包構建出來的全释,這個之后的部分會進行說明。
GOPATH 環(huán)境變量
GOPATH環(huán)境變量指定工作區(qū)的位置误债。它缺省為用戶目錄中名為go的目錄浸船,因此在Linux上為$HOME/go,在Windows上通常為C:\Users\YourName\Go寝蹈。
如果想在其他位置放置工作區(qū)李命,則需要將GOPATH設置為該目錄的路徑。請注意箫老,GOPATH不得與GO安裝路徑相同封字。
命令go env GOPATH打印當前有效的GOPATH;如果環(huán)境變量未設置,它將打印默認位置周叮。為方便起見辩撑,可以請將工作區(qū)的bin子目錄添加到系統(tǒng)環(huán)境變量$PATH中
$ export PATH=$PATH:$(go env GOPATH)/bin
同時也把GOPATH設置成系統(tǒng)的環(huán)境變量:
$exportGOPATH=$(go env GOPATH)
包的導入路徑
一個***導入路徑***是用來唯一標識包的字符串界斜,包的導入路徑和他在工作區(qū)中的位置相對應仿耽。標準庫中的包具有較短的導入路徑,如“fmt”和“net/http”各薇。對于您自己的軟件包项贺,你必須選擇一個不太可能與將來添加到標準庫或其他外部庫中的內容沖突的基本路徑。
如果你將代碼保存在某個源代碼庫中峭判,那么應該使用該源代碼庫的根目錄作為你的基本路徑开缎。例如,如果你在github.com上有一個GitHub帳戶user林螃,你創(chuàng)建的倉庫都會以 github.com/user 為前綴奕删,那么github.com/user這應該是你的基本路徑。
請注意疗认,在構建代碼之前完残,你不需要將代碼發(fā)布到遠程存儲庫。就像有一天會發(fā)布代碼一樣來組織代碼横漏,這是一個好習慣谨设。實際上,您可以選擇任意路徑名缎浇,只要它是唯一的扎拣。
我們將使用github.com/user作為基本路徑。在工作區(qū)內創(chuàng)建一個保存源代碼的目錄:
$mkdir -p$GOPATH/src/github.com/user
你的第一個Go程序
要編譯并運行一個簡單的程序素跺,首先選擇一個軟件包路徑(我們將使用github.com/user/hello)二蓝,并在您的工作區(qū)內創(chuàng)建一個相應的軟件包目錄:
$mkdir$GOPATH/src/github.com/user/hello
接下來,在該目錄中創(chuàng)建一個名為hello.go的文件指厌,添加以下代碼:
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
現(xiàn)在刊愚,你可以使用go工具構建和安裝該程序了:
$ go install github.com/user/hello
你可以從系統(tǒng)上的任何位置運行此命令。go命令工具通過在GOPATH指定的工作區(qū)內查找github.com/user/hello包來查找源代碼仑乌。如果從軟件包目錄運行go Install百拓,可以省略軟件包路徑:
$cd$GOPATH/src/github.com/user/hello$ go install
go install構建hello命令,生成一個可執(zhí)行的二進制文件晰甚。然后衙传,它將該二進制文件作為hello(在Windows下為hello.exe)安裝到工作區(qū)的bin目錄中,hello 可執(zhí)行命令的位置為$GOPATH/bin/hello厕九。
Go工具僅在發(fā)生錯誤時打印輸出蓖捶,因此如果這些命令沒有產生輸出,則代表它們已成功執(zhí)行扁远。
現(xiàn)在俊鱼,你可以通過在命令行中鍵入程序的完整路徑來運行該程序:
$ $GOPATH/bin/hello
Hello, world.
由于您已將$GOPATH/bin添加到路徑中刻像,因此只需鍵入二進制文件的名字:
$ helloHello, world.
你的第一個 library
讓我們編寫一個庫并在上面寫的hello程序中使用它。
同樣并闲,第一步是選擇軟件包路徑(我們將使用github.com/user/stringutil)并創(chuàng)建軟件包目錄:
$mkdir$GOPATH/src/github.com/user/stringutil
接下來在目錄中創(chuàng)建reverse.go文件并添加如下代碼:
// stringutil包 存放關于字符串的工具函數(shù)
package stringutil
// Reverse 將參數(shù)中的字符串反轉后的字符串
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
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 程序后運行他犀填,可以看到輸出中的字符串已經被反轉了蠢壹。
$ helloHello, Go!
經過上面幾步后你的工作區(qū)現(xiàn)在應該看起來像下面這樣:
bin/
? ? hello? ? ? ? ? ? ? ?
src/
? ? github.com/user/
? ? ? ? hello/
? ? ? ? ? ? hello.go? ? ?
? ? ? ? stringutil/
? ? ? ? ? ? reverse.go? ?
包名
go 源碼文件中的第一行語句必須是:
packagename
其中,name是用于導入的包的默認名稱九巡。(包中的所有文件必須使用相同的名稱)
go的慣例是包名是導入路徑的最后一個元素:作為“crypto/rot13”導入的包它的包名為rot13图贸。
生成可執(zhí)行命令的源碼文件必須以main作為包名。
go 中不要求鏈接到單個二進制文件的所有包的包名都是唯一的冕广,只要求導入路徑(它們的完整文件名)是唯一的疏日。
測試
go有一個由go測試命令和測試包組成的輕量級測試框架。你可以通過創(chuàng)建一個名字以_test.go結尾的文件來編寫測試佳窑,該文件包含名為TestXXX的函數(shù)制恍,簽名函數(shù)為func(t*testing.T)。測試框架運行每個這樣的函數(shù)神凑;如果函數(shù)調用失敗函數(shù)净神,如t.Error或t.Fail,則認為測試失敗溉委。
通過創(chuàng)建包含以下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
導入路徑可以描述如何從版本控制系統(tǒng)(如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!
如果工作區(qū)中沒有指定的包棵帽,go get將把它放在$GOPATH指定的工作區(qū)中熄求。(如果軟件包已經存在,go get將跳過遠程獲取逗概,其行為變得與go install相同弟晚。)。
發(fā)出上述go get命令后,工作區(qū)目錄樹現(xiàn)在應該如下所示:
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"
最后:
上面都是自己整理好的瑟押!我就把資料貢獻出來給有需要的人搀捷!順便求一波關注,哈哈~各位小伙伴關注我后私信【Java】就可以免費領取噠
鏈接:https://juejin.im/post/5e06a300518825125135462a