了解 Go 中的上下文
上下文是 Go 中支持並發的關鍵特性之一。在 Go 中,“上下文”指的是一個包,它為跨 API 邊界的請求範圍的值和取消信號提供功能。
基於 goroutines 的概念,上下文包與 Go 的並發模型同時工作。Goroutine 是輕量級的執行線程,您可以高效地創建和管理它,從而可以輕鬆地在 Go 中創建並發程序。
上下文包
context 包提供了取消長時間運行的函數或整個調用鏈的功能。該包還有助於存儲請求範圍內的值,以便在調用鏈中的任何位置訪問。在使用 API 或微服務時,此功能非常方便,其中請求可能跨越多個函數調用,並且您想要取消它們或將特定值附加到它們。
以下是如何在 Go 程序中導入上下文包。
import "context"
上下文函數採用上下文包的上下文結構類型。按照慣例,您應該使用ctx作為實例變量的名稱。
func operations(ctx context.Context) {
}
函數可以為其他函數和操作返回 Context 結構類型。
func operations(ctx context.Context) context.Context {
}
您可以使用 context 包的TODO函數創建一個新的上下文。TODO 函數創建一個值為context.Done()的新上下文,一個將在上下文取消時關閉的通道。當您需要上下文但沒有合適的父上下文時,您應該將它用作佔位符。
import "context"
func main() {
ctx: = context.TODO()
}
或者,Background函數創建一個沒有值的新上下文和一個空的 Done 通道。
ctx: = context.Background()
您應該使用 Background 函數作為上下文樹的根。
價值觀的背景
上下文包提供傳播值和取消信號的功能。您可以將這些值用於從請求範圍的數據到取消信號和截止日期的信息。
context 包還允許創建從父上下文繼承的子上下文,允許在整個程序中有效地處理值和取消信號,因為您可以通過多個函數傳遞上下文。
下面是使用 context 包通過函數傳遞上下文的示例。
import (
"context"
)
func valuableContext(ctx context.Context) context.Context {
return context.WithValue(ctx, "pass-key", "hfouneqcelkwfu")
}
func receiveContextData(ctx context.Context) any {
passKey: = ctx.Value("pass-key")
return passKey
}
valuableContext函數接受一個上下文實例並為以下函數返回一個上下文實例。上下文實例是使用WithValue方法創建的值。WithValue 方法從函數和鍵值對中獲取上下文實例。
要從上下文中檢索數據,您需要使用TODO或Background函數創建一個新的上下文並將上下文傳遞給該函數(在本例中為 valuedContext)並使用receiveContextData函數接收上下文。
func main() {
ctx: = context.Background()
ctx = valuableContext(ctx)
fmt.Println(receiveContextData(ctx))
}
ctx 變量是背景函數的上下文實例。valuedContext 函數接收 ctx 變量並返回具有值的上下文,receiveContextData 函數接收該值並返回鍵值對中的值。
上下文超時和截止日期
上下文包提供了在操作中設置超時和截止日期的功能。設置超時和截止日期對於需要趕上進度的操作很有幫助。
超時是操作所花費的時間。您可以將操作的超時時間設置為 4 秒;之後,上下文取消請求。
另一方面,截止日期定義了操作應該取消的絕對時間點。
您可以使用WithTimeout方法設置上下文超時。以下是設置 2 秒超時的方法。
func main() {
ctx, cancel: = context.WithTimeout(context.Background(), 2 * time.Second)
defer cancel()
// some operation
}
main函數創建一個超時為兩秒的上下文。WithTimeout 函數返回一個取消函數,您可以在主函數退出時推遲取消。
您可以使用WithDeadline方法聲明截止日期。WithDeadline 方法採用上下文實例和截止時間。
func doSomething(ctx context.Context) {
deadlineTime: = time.Now().Add(1500 * time.Millisecond)
ctx, ctxCancel: = context.WithDeadline(ctx, deadlineTime)
defer ctxCancel()
// some operation
ctxCancel()
}
doSomething函數接受一個上下文,而deadlineTime變量是上下文截止時間之前的時間。ctx變量是具有截止日期的上下文。
當上下文超過其最後期限時,ctxCancel變量會取消上下文。
在 Go 中使用上下文的最佳實踐
避免使用上下文作為全局變量。使用上下文作為全局變量可能會導致意外的代碼行為和難以跟踪的錯誤,並謹慎使用上下文以降低代碼複雜性。
最後,使用上下文作為信號,而不是保證。取消上下文並不能保證所有的 goroutines 都會停止運行;它只是一個信號,goroutines 與上下文無關。
發佈留言