不寫測試的開發不是好程序員,我個人非常崇拜TDD Test Driven Development 的,然而可惜的是國內的程序員
都不太關注測試這一部分,這篇文章主要介紹下在Go語言中如何做單元測試和基準測試。
go test 工具
Go 語言中的測試依賴go test 命令。編寫測試代碼和編寫普通的Go代碼過程是類似的,並不需要學習新的語法。
規則或工具
go test 命令是一個按照一定約定和組織的測試代碼的驅動程序,在包目錄內,所有以——test,go 爲後綴名
的源代碼文件都是 go test 測試的一部分,不會被go build 編譯到最終的可執行文件中。
在 *_test.go 文件中有三種類型的函數,單元測試函數、基準測試函數和示例函數。
測試函數 函數名前綴爲Test 測試程序的一些邏輯行爲是否正確
基準函數 函數名前綴爲Benchmark 測試函數的性能
示例函數 函數名前綴爲Example 爲文檔提供示例
go test 命令會遍歷所有的*_test.go文件彙總符合上述命名規則的函數,然後生成一個臨時的main包用於
調用相應的測試函數,然後構建並運行,報告測試結果,最後清理測試中生成的臨時文件
Conytext 初識
Go1.7加入了一個新的標準庫context,它定義了 Context類型,專門用來簡化對於處理單個請求的多個goroutine之間
與請求域的數據,取消信號。截止時間等相關操作,這些操作可能涉及多個API調用。
對服務器傳入的請求應該創建上下文,而對服務器的傳出調用應該接受上下文。他們之間的函數調用鏈必須傳遞上下文,或者可以使用WithCancel WithDeadline
WithTimeout 或WithValue創建的派生上下文,當一個上下文被取消時,它派生的所有上下文也被取消
Context接口
contexty.Context 是一個接口,改接口定義了四個需要實現的方法,具體簽名如下:
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <- chan struct{}
Err() error
Value(key interface{}) interface{}
}
其中
Deadline 方法需要返回當前Context被取消的時間,也就是完成工作的截止時間deadline
Done方法需要返回一個Channel ,這個Channel會在當前工作完成或者上下文被取消之後關閉,多次調用
Done方法會範湖同一個Channel;
Err方法會返回當前Context結束的原因,它只會在Done返回的Channel被關閉時纔會返回非空的值;
如果當前的Context被取消就會返回Canceled錯誤;
如果當前Context超時就會返回DeadlineExceeded錯誤;
Value方法會從Context中返回鍵對應的值,對於同一個上下文來說,多次調用Value並傳入相同的Key
會返回相同的結果,該方法僅用於傳遞跨API和進程間跟請求域的數據;
Background() 和TODO()
Go內置兩個函數:Background()和TODO(),這兩個函數分別返回了一個實現了Context接口的background
和todo.我們代碼中最開始都是以這兩個內置的上下文對象作爲最頂層的partent context ,衍生出更多的子
上下文對象。
Background() 主要用於main函數,初始化以及測試代碼中,作爲Context這個樹結構的最頂層的Context,也就是
Context.
TODO() 它目前還不知道具體的使用場景,如果我們不知道該使用什麼Context的時候,可以使用這個
background 和 todo 本質上都是emptyCtx 結構體類型,是一個不可取消,沒有設置截止時間,沒有攜帶任何值得
Context。
With系列函數
此外,context 包中還定義了四個With系列函數。
WithCancel
返回帶有新Done通道的父節點的副本。當調用返回的cancel函數或當關閉父上下文的Done通道時,將關閉返回上下文的Done通道,無論先發生什麼情況。
取消此上下文將釋放與其關聯的資源,因此代碼應該在此上下文中運行的操作完成後立即調用cancel
WithDeadline
返回父上下文的副本,並將deadline調整爲不遲於d,如果父上下文的deadline已經早於d,則WithDeadline(
parent,d)在語義上等同於父上下文。當截止日過期時,調用返回的cancel函數時,或者當父上下文的Done
通道關閉時,返回上下文的Done通道即將關閉,以最先發生的情況爲準。
取消此上下文將釋放與其關聯的資源,因此代碼應該在此上下文中運行的操作完成後立即調用cancel
WithTimeout
取消此上下文將釋放與其相關的資源,因此代碼應該在此上下文中運行的操作完成後理解調用
cancel,通常用於數據庫或者網絡連接的超時控制。
WithValue
返回父節點的副本,其中與key關聯的值爲val.
僅對api和進程間傳遞請求域的數據使用上下文,而不是使用它來傳遞可選參數給函數。
所提供的健必須是可以比較的,並且不應該是string類型或任何其他內置類型,以避免使用上下文在包之間
發生衝突。withValue 的用戶應該爲健定義自己的類型。爲了避免在分配給interface {} 時進行分配,上下文
健通常具有具體類型struct{} 。或者,導出的上下文關鍵變量的靜態類型應該是指針或接口。
使用Context的注意事項
推薦以參數的方式顯示傳遞Context
以Context作爲參數的函數方法,應該把Context作爲第一個參數。
給一個函數方法傳遞Context的時候,不要傳遞nil,如果不知道傳遞什麼,就是用context.TODO()
Context的Value相關方法應該傳遞請求域的必要參數,不應該用於傳遞可選參數
Context 是線程安全的,可以放心的在多個goroutine 中傳遞
Zookeeper
是一個分佈式的,開放源碼的分佈式應用程序協調服務,是Google的Chubby一個開源的
實現,它是集羣的管理者,監視者集羣中各個節點的狀態根據節點提交的反饋進行
下一步合理操作。最終,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶