在 Go 中,上下文套件是一個基本工具,旨在管理和共享應用程式不同層的請求範圍資料、取消訊號以及逾時或截止日期。
context.Context 類型提供了一種以可連結、分層的方式攜帶截止日期、取消訊號和其他請求範圍值的方法。它被設計為不可變的,這意味著每個新的派生上下文都攜帶其父上下文的屬性,同時添加新的值或行為。
將上下文想像為一個特殊的手提袋,其中包含特定任務的所有必要資訊和說明。這個包可以從一個函數傳遞到另一個函數,確保涉及的每個人都具有相同的上下文(訊息)並且可以採取相應的行動。它還可以包含一個自毀按鈕(取消訊號),以便在需要時停止操作。
在 Go 中引入 Context 之前,管理請求範圍的資料和取消訊號是一項繁瑣的任務。開發人員必須依靠臨時解決方案(例如傳遞自訂結構或使用全域變數)來在函數和 goroutine 之間共享資料和訊號。然而,這些方法容易出錯、難以維護,並且經常導致組件之間的緊密耦合。
程式中的許多操作都是非同步、並發或依賴外部系統,因此需要上下文。在這種情況下,必須有一種方法可以跨多個函數和 goroutine 傳播取消訊號、截止日期和請求範圍的資料。
讓我們考慮幾個場景來說明對 Context 的需求:
想像一下您是一家熙熙攘攘的餐廳裡接受訂單的人。當訂單到達時,您將其分配給一位熟練的廚師。但如果客戶突然決定要離開怎麼辦?你會毫不猶豫地通知廚師停止處理該訂單,以免浪費食材。此場景反映了 Go 中上下文的工作方式。
假設您的應用程式向外部 API 發出 Web 請求或執行系統命令。在生產級系統中,設定逾時至關重要。原因如下:
API 依賴性:想像一下您的服務依賴外部 API。如果該 API 運作緩慢或變得無回應,您不希望系統以待處理的請求進行備份。逾時可確保如果 API 呼叫超過指定的持續時間,關聯的上下文就會取消,使您的應用程式優雅地處理這種情況。
效能下降:沒有超時,外部速度慢
依賴可能會導致級聯效應。積壓的請求會增加負載、降低效能並影響整體系統回應能力。透過使用帶有截止日期的上下文,您可以防止此問題。
Go 中的上下文套件用途廣泛,可用於各種場景來管理請求範圍的資料、取消訊號和逾時。
以下是一些常見的現實用例:
1。跨分散式服務傳播追蹤 ID
在微服務架構中,追蹤不同服務之間的請求對於監控和除錯至關重要。上下文包可讓您跨服務邊界傳播追蹤 ID 和其他元數據,確保在整個請求生命週期中日誌記錄和追蹤資訊的一致性。
2。傳遞身份驗證令牌
在許多應用程式中,身份驗證令牌或使用者資訊需要透過應用程式的不同層傳遞。 context 套件提供了一種乾淨的方法來處理這個問題,確保身份驗證資訊在需要時可用,而不會用附加參數污染函數簽署。
3。 WebSocket 和流 API
在 WebSocket 和流 API 中,Context 用於管理連接的生命週期並傳播請求範圍的數據,例如使用者 ID 和會話資訊。這使您可以有效地實現身份驗證、速率限制和會話管理等功能。
Go 中的 context 套件提供了多種建立和操作 context 物件的方法。以下是常用類型的細分:
這是最基本的上下文,可以作為一個空的起點。它不帶有任何取消訊號或截止日期。當不需要特定上下文時使用它。
唯一使用 TODO 代替 Background 的時候是當實作不清楚,或是上下文還不知道的時候。
通常用於主函數、初始化和測試。
ctx := context.Background()
ctx2 := context.TODO()
建立一個從父上下文派生的新上下文。 WithCancel 方法傳回父上下文的副本以及取消函數;呼叫取消函數會釋放與上下文相關的資源,並且應在 Context 類型中的操作最終完成後立即呼叫。
用於在滿足某些條件時取消 Goroutine 中的操作。
parentCtx := context.Background()
ctx, 取消 := context.WithCancel(parentCtx)
defer cancel() // 清理資源
與為自己設定截止日期類似,您可以根據上下文設定截止日期。如果達到您指定的完成時間限制,Go 將自動為您取消上下文。它會建立一個從父上下文派生的新上下文,並具有特定的截止日期。
當您有完成操作的特定截止日期時很有用。
parentCtx := context.Background()
截止日期 := time.Now().Add(10 * time.Second)
ctx, 取消 := context.WithDeadline(parentCtx, 最後期限)
defer cancel() // 清理資源
使用關聯的鍵值對建立從父上下文派生的新上下文。這允許您在上下文中儲存和檢索特定於請求的資訊。 WithValue 接受父上下文並傳回上下文副本。因此,它不會覆蓋該值,而是使用新的鍵值對建立新的重複項。
用於透過上下文傳遞請求範圍的數據,例如身份驗證令牌或追蹤 ID。
parentCtx := context.Background()
userIDKey := "auth-token"
ctx := context.WithValue(parentCtx, userIDKey, "abc123")
建立具有關聯逾時的上下文。上下文在指定的持續時間後自動取消。 WithTimeout,讓程式在可能掛起的地方繼續運行,為最終用戶提供更好的體驗。它接受一個簡短的時間段作為參數以及父上下文,如果函數運行超出超時時間,則終止函數。
對於設定操作截止日期很有用。
parentCtx := context.Background()
ctx, 取消 := context.WithTimeout(parentCtx, 5*time.Second)
defer cancel() // 清理資源
現在我們已經探索了 Go 中上下文的力量,讓我們深入研究 GoFr 如何透過 GoFr Context 更進一步。
GoFr 是一個建構在 Go 之上的固執己見的微服務開發框架。它旨在透過提供建構健壯且可擴展的微服務的結構化方法來簡化開發流程。
GoFr Context 透過建立一個包裝器,完美地擴展了標準 Go 上下文包的功能。此包裝器提供了一組豐富的預先配置依賴項,可透過上下文物件直接存取。這個完全載入的上下文使開發人員能夠從單一上下文物件無縫存取日誌記錄、資料庫連接、底層服務、追蹤和指標 - 。
func MyHandler(c *gofr.Context) (interface{}, error) { // Logging c.Info("Processing request...") // Database access var value int err := c.SQL.QueryRowContext(c, "select 2+2").Scan(&value) if err != nil { return nil, datasource.ErrorDB{Err: err, Message: "error from sql db"} } // Accessing another service resp, err := c.GetHTTPService("anotherService").Get(c, "book", nil) if err != nil { return nil, err } // Creating a tracing span span := c.Trace("some-sample-work") defer span.End() // ... perform some work return value, nil }
在此範例中,請注意我們如何直接透過GoFr Context 物件存取日誌記錄(c.Info)、資料庫互動(c.SQL)、服務呼叫(c.GetHTTPService) 和追蹤(c.Trace) 等功能(c).
GoFr 上下文可在所有 HTTP 處理程序中使用,透過提供集中方式來管理應用程式的不同方面,從而大大改善開發體驗。這種整合確保開發人員可以專注於業務邏輯,同時利用 GoFr 的功能進行有效的上下文管理。
在程式設計方面,Golang 上下文套件是一個非常有用的工具。 Go 中的上下文是管理請求範圍資料、取消訊號和截止日期的強大工具。無論您是建立微服務、API 還是 Web 應用程序,上下文都能確保乾淨的資源處理和一致的行為。
請查看 GoFr 及其 Github Repo,並給它 ⭐ 來支持它。
以上是理解並利用 Go 和 GoFr. 中的上下文的詳細內容。更多資訊請關注PHP中文網其他相關文章!