介紹
這篇檔案將演示如何在模塊中開發一個簡單的 Go 包,并介紹 Go 工具,獲取、構建和安裝 Go 模塊和包的標準方法,以及相關的命令,
注意:這篇檔案假定你使用 Go 1.13 及以上版本,并且未設定 GO111MODULE 環境變數,
代碼組織
Go 程式被組織在包中,包(Packege)是同一目錄下的源檔案的集合,這些源檔案將會被一起編譯,定義在一個源檔案中的函式、型別、變數和常量,對同一個包中的其他所有源檔案都是可見的,
一個倉庫可以包含一個或多個模塊,模塊(Module)是一組相關的包的集合,這些包會被一起發布,Go 倉庫(Repository)通常只包含一個位于倉庫根目錄的模塊,其中的 go.mod 檔案宣告了模塊路徑:該模塊下所有包的匯入路徑的前綴,模塊包含 其 go.mod 檔案所在的目錄下的所有包 及 該目錄的子目錄,直到下一個子目錄包含另一個 go.mod 檔案(如果有的話),
你不必在代碼可以運行前就將其發布到遠程倉庫,因為模塊可以在本地被定義,而無需屬于一個代碼倉庫,然而,抱著你某天會發布它的態度去組織代碼,無疑是一個良好的習慣,
每個模塊的路徑不僅作為其所含包的匯入路徑的前綴,而且指示 go 命令應該到哪里去下載這個模塊,比如為了下載 golang.org/x/tools 模塊,go 命令會查詢 https://goalng.org/x/tools 所指示的倉庫(詳見此網頁),
匯入路徑是一個用于匯入包的字串,包的匯入路徑由模塊路徑及模塊內的子目錄組合而成,例如,github.com/google/go-cmp 模塊包含一個位于 cmp/ 目錄中的包,那么這個包的匯入路徑就是 github.com/google/go-cmp/cmp,標準庫中的包沒有模塊路徑作為前綴,
你的第一個程式
在編譯并運行一個簡單的程式之前,首先選擇一個模塊路徑(我們將使用 example/user/hello),然后創建一個 go.mod 檔案來宣告這個模塊:
$ mkdir hello # 如果已經存在于版本控制中,也可以直接克隆
$ cd hello
$ go mod init example/user/hello
go: creating new go.mod: module example/user/hello
$ cat go.mod
module example/user/hello
?
go 1.16
$
Go 源檔案中第一個陳述句必須是 package 模塊名,可執行的程式必須使用package main,
接下來在目錄中創建一個名為 hello.go 的檔案,該檔案包含以下 Go 代碼:
package main
?
import "fmt"
?
func main() {
fmt.Println("Hello, world.")
}
現在你可以使用 go 工具構建并安裝這個程式,
$ go install example/user/hello
$
該命令將構建一個 hello 命令,生成一個可執行的二進制檔案,之后將該二進制檔案安裝到 $HOME/go/bin/ 目錄下(在 Windows 系統中是 %USERPROFILE%\go\bin),
安裝目錄由 GOPATH 和 GOBIN 環境變數控制,如果設定了 GOBIN,那么二進制檔案會被安裝到這個目錄,如果設定了 GOPATH,二進制檔案會被安裝到 GOPATH 串列中的第一個目錄的 bin 子目錄中,否則二進制檔案會被安裝進默認 GOPATH($HOME/go 或是 %USERPROFILE%\go)的 bin 子目錄中,
你可以使用 go env 命令來為 go 命令設定默認環境變數:
$ go env -w GOBIN=/somewhere/else/bin
$
要重置之前使用 go env -w 命令設定的變數,使用 go env -u 命令:
$ go env -u GOBIN
當前作業目錄(working directory)包含在模塊中時,像 go install 這樣的命令可以正常運行,如果作業目錄不在 example/user/hello 模塊內,go install 命令可能會執行失敗,
go 命令接受作業目錄的相對路徑;如果沒有給出路徑,默認為當前作業目錄下的包,所以在我們的作業目錄中,以下命令效果一致:
$ go install example/user/hello
$ go install .
$ go install
接下來讓我們運行程式,確保它正常作業,為了更加簡便地運行二進制檔案,我們將把安裝目錄加入 PATH 環境變數,以下僅演示 Linux 系統的操作程序,Windows 用戶參見此網頁,
$ export PATH=$PATH:$(dirname $(go list -f '{{.Target}}' .))
$ hello
Hello, world.
$
如果你正在使用版本控制系統,現在是初始化倉庫的好時機,加入檔案然后提交你的第一個改動,當然,這一步不是必需的,你并不一定要使用版本控制來撰寫 Go 代碼,
$ git init
Initialized empty Git repository in /home/user/hello/.git/
$ git add go.mod hello.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
1 file changed, 7 insertion(+)
create mode 100644 go.mod hello.go
$
go 命令通過請求相應的 https url 并讀取嵌入在 HTML 回應中的元資料,來定位包含指定模塊的倉庫(詳見此網頁),因為許多代碼托管服務已經為 Go 代碼倉庫提供了這樣的元資料,所以讓你的模塊能被其他人使用的最簡單的方法是讓其 模塊路徑 與 代碼倉庫的 url 一致,
從你的模塊匯入包
讓我們撰寫一個 morestrings 包,并從 hello 程式中使用它,首先,為這個包創建一個目錄,命令為 $HOME/hello/morestrings,然后在這個目錄中創建一個名為 reverse.go 的檔案,包含以下代碼:
// 與標準string包提供的函式相比,morestrings包
// 實作額外的的功能來操作UTF-8編碼字串
package morestrings
?
// ReverseRunes函式回傳其字串引數的逆序字串
func ReverseRunes(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)
}
因為我們的 ReverseRunes 函式以一個大寫字母開頭,所以它是可匯出的(Exported),即可以在其他匯入了 morestrings 包的包中使用,
讓我們測驗一下,使用 go build 命令編譯,
$ cd $HOME/hello/morestrings
$ go build
$
這不會在當前目錄生成可執行檔案,而是將編譯后的包保存在本地構建快取中,
在確認 morestring 包構建完成后,讓我們在 hello 程式中使用它,首先修改原來的 $HOME/hello/hello.go 檔案,讓其匯入 morestrings 包:
package main
import (
"fmt"
"example/user/hello/morestrings"
)
func main() {
fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
}
安裝 hello 程式:
$ go install example/user/hello
運行新版本的 hello 程式,你會看見一條新的,順序顛倒過的資訊:
$ hello
Hello, Go!
從遠程模塊匯入包
當你使用Git或Mercurial這樣的版本控制系統時,匯入路徑能夠描述如何獲取包的原始碼,go 工具使用這一特性來從遠程倉庫自動獲取包,例如,要在你的程式中使用 github.com/google/go-cmp/cmp:
package main
import (
"fmt"
"example/user/hello/morestrings"
"github.com/google/go-cmp/cmp"
)
func main() {
fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
fmt.Println(cmp.Diff("Hello World", "Hello Go"))
}
由于你依賴了外部模塊,你需要下載這個模塊并將其版本記錄在 go.mod 檔案中,go mod tidy 命令為匯入的包添加缺失的模塊需求(Module Requirements),并移除不再使用的模塊需求,
$ go mod tidy
go: finding module for package github.com/google/go-cmp/cmp
go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.5.4
$ go install example/user/hello
$ hello
Hello, Go!
string(
- "Hello World",
+ "Hello Go",
)
$ cat go.mod
module example/user/hello
go 1.16
require github.com/google/go-cmp v0.5.4
$
模塊依賴會被自動下載到 GOPATH 環境變數指向的目錄的包/模塊子目錄,對于一個指定版本的模塊,其下載內容會被所有依賴該版本的其他模塊共享,因此 go 命令會將這些檔案和目錄標記為只讀,要移除全部下載的模塊,你可以使用 go clean -modcache 命令,
測驗
Go 有一個輕量級的測驗框架,由 go test 命令和 testing 包組成,
你通過創建以 _test.go 結尾的檔案撰寫測驗,該檔案中包含函式名以 Test 開頭,函式簽名為 func(t *testing.T) 的函式,測驗框架會運行每一個這樣的函式;如果一個函式呼叫了錯誤函式(Failure Function),比如 t.Error 或 t.Fail,則測驗被視作失敗,
為 morestring 包增加一個測驗,創建檔案 $HOME/hello/morestrings/reverse_test.go ,該檔案包含以下代碼:
package morestrings
import "testing"
func TestReverseRunes(t *testing.T) {
cases := []struct {
in, want string
}{
{"Hello, world", "dlrow ,olleH"},
{"Hello, 世界", "界世 ,olleH"},
{"", ""},
}
for _, c := range cases {
got := ReverseRunes(c.in)
if got != c.want {
t.Errorf("ReverseRunes(%q) == %q, want %q", c.in, got, c.want)
}
}
}
然后使用 go test 命令運行該測驗:
$ cd $HOME/hello/morestrings
$ go test
PASS
ok example/user/hello/morestrings 0.165s
$
運行 go help test 或訪問 testing 包檔案 以獲取更多詳情,
本文譯自 https://go.dev/doc/code,有刪改
未經許可,不得轉載
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/517766.html
標籤:其他
