包的定義
包是函數和資料的集合,使用pacakge關鍵字開始包的定義。檔案名不需要與包名一緻,包名使用小寫字母。包可以由多個檔案組成,但是每個檔案都要使用相同的
package <name>
這一行,
name
為包的名字。
例如我們在檔案even.go中,使用包名even定義一個包。
package even <--開始定義包
func Even(i int) bool { <--導出的函數
return i ==
}
func odd(i int) bool { <--私有函數
return i ==
}
以大寫字母開頭的名字是可以導出的,可以在包的外部通路。小寫字母開頭的名字為私有的,隻能在包内部通路。
現在建構這個包,在$GOPATH下建立一個目錄,将even.go拷貝到目錄下
$ mkdir $GOPATH/src/even
$ cp even.go $GOPATH/src/even/
$ go build
$ go install even
建構完成後就可以在myeven.go代碼裡引用這個包:
package main
import (
"even" <--導入even包
"fmt"
)
func main(){
fmt.Printf("2 is even : %v\n", even.Even()); <--調用even包中的函數
}
調用某個包中函數的寫法是
<packagename>.Function()
在 Go 中,當函數的首字母大寫的時候,函數會被從包中導出(在包外部可見,或者說公有的),是以函數名是 Even 。如果修改 myeven.go 的第 10 行,使用未導出的函數even.odd :
fmt.Printf(“Is %d even? %v\n”, i, even.odd(i))
由于使用了 私有 的函數,會得到一個編譯錯誤:
myeven.go:10: cannot refer to unexported name even.odd
概括來說:
• 公有函數的名字以 大寫 字母開頭;
• 私有函數的名字以 小寫 字母開頭。
測試包
在 Go 中為包編寫單元測試應當是一種習慣。編寫測試需要包含 testing 包和程式 go test 。兩者都有良好的文檔。
go test 程式調用了所有的測試函數。even 包沒有定義任何測試函數,執行 go test ,這樣:
$ go test
? even [no test files]
在 測 試 文 件 中 定 義 一 個 測 試 來 修 複 這 個。 測 試 文 件 也 在 包 目 錄 中, 被 命 名 為*_test.go 。 這些測試檔案同 Go 程式中的其他檔案一樣, 但是 go test 隻會執行測試函數。每個測試函數都有相同的辨別,它的名字以 Test 開頭:
func TestXxx(t *testing.T)
編寫測試時,需要告訴 go test 測試是失敗還是成功。測試成功則直接傳回。當測試失敗可以用下面的函數标記 。這是非常重要的(參閱 go doc testing 或 go help testfunc 了解更多):
func (t *T) Fail()
Fail 标記測試函數失敗,但仍然繼續執行。
func (t *T) FailNow()
FailNow 标記測試函數失敗,并且中斷其執行。目前檔案中的其餘的測試将被跳過,然後執行下一個檔案中的測試。
func (t *T) Log(args … i n t e r f a c e { } )
Log 用預設格式對其參數進行格式化,與 Print() 類似,并且記錄文本到錯誤日志。
func (t *T) Fatal(args … i n t e r f a c e { } )
Fatal 等價于 Log() 後跟随 FailNow() 。
将這些湊到一起,就可以編寫測試了。首先,選擇名字 even_test.go 。然後添加下面的内容:
Listing. even 包的測試
package even
import "testing"
func TestEven(t *testing.T) {
if ! Even) {
t.Log("2 should be even ! ")
t.Fail()
}
}
注意在第一行使用了 package even ,測試使用與被測試的包使用相同的名字空間。這不僅僅是為了友善,也允許了測試未導出的函數和結構。然後導入 testing 包,并且在第 5 行定義了這個檔案中唯一的測試函數。展示的 Go 代碼應當沒有任何驚異的地方,檢查了 Even 函數是否工作正常。現在等待了好久的時刻到了,執行測試:
% go test
ok even s
測試執行并且報告 ok 。成功了!
如果重新定義測試函數,就可以看到一個失敗的測試:
// Entering the twilight zone
func TestEven(t *testing.T) {
if Even() {
t.Log("2 should be odd ! ")
t.Fail()
}
}
然後得到:
$ go test even
--- FAIL: TestEven (.s)
even_test.go:8: 2 should be Even!
FAIL
FAIL even 0.002s
然後你可以以此行事(修複測試的執行個體)
!!!! 在編寫包的時候應當一邊寫代碼,一邊寫(一些)文檔和測試函數。這可以讓你的程式更好,并且它展示了你的努力。
The Go test suite also allows you to incorperate example functions which serve as documentation and as tests. These functions need to start with Example .
func ExampleEven() {
if Even) {
fmt.Printf("Is Even\n")
}
//Output:
//Is Even
}
Those last two comments lines are part of the example, go test uses those to check the generated output with the text in the comments. If there is a mismatch the test fails.
常用的包
fmt
包 fmt 實作了格式化的 I/O 函數,這與 C 的 printf 和 scanf 類似。格式化短語派生于 C 。一些短語(%-序列)這樣使用:
%v
預設格式的值。當列印結構時,加号(%+v)會增加字段名;
%#v
Go 樣式的值表達;
%T
帶有類型的 Go 樣式的值表達;
io
這個包提供了原始的 I/O 操作界面。它主要的任務是對 os 包這樣的原始的 I/O 進行封裝,增加一些其他相關,使其具有抽象功能用在公共的接口上。
bufio
這個包實作了緩沖的 I/O。它封裝于 io.Reader 和 io.Writer 對象,建立了另一個對象(Reader 和 Writer)在提供緩沖的同時實作了一些文本 I/O 的功能。
sort
sort 包提供了對數組和使用者定義集合的原始的排序功能。
strconv
strconv 包提供了将字元串轉換成基本資料類型,或者從基本資料類型轉換為字元串的功能。
os
os 包提供了與平台無關的作業系統功能接口。其設計是 Unix 形式的。
sync
sync 包提供了基本的同步原語,例如互斥鎖。
flag
flag 包實作了指令行解析。
encoding/json
encoding/json 包實作了編碼與解碼 RFC 4627 [2] 定義的 JSON 對象。
html/template
資料驅動的模闆,用于生成文本輸出,例如 HTML。将模闆關聯到某個資料結構上進行解析。模闆内容指向資料結構的元素(通常結構的字段或者 map 的鍵)控制解析并且決定某個值會被顯示。模闆掃描結構以便解析,而 “遊标” @ 決定了目前位置在結構中的值。
net/http
net/http 實作了 HTTP 請求、響應和 URL 的解析,并且提供了可擴充的 HTTP 服務和基本的 HTTP 用戶端。
unsafe
unsafe 包包含了 Go 程式中資料類型上所有不安全的操作。 通常無須使用這個。
reflect
reflect 包實作了運作時反射,允許程式通過抽象類型操作對象。通常用于處理靜态類型 interface{} 的值,并且通過 Typeof 解析出其動态類型資訊,通常會傳回一個有接口類型 Type 的對象。
os/exec
os/exec 包執行外部指令。