AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

Go語言高級特性:Context深入解讀

來源: 責編: 時間:2023-11-01 09:18:43 239觀看
導讀概述在 Go 語言中,context(上下文)是一個非常重要的概念。它主要用于在多個 goroutine 之間傳遞請求特定任務的截止日期、取消信號以及其他請求范圍的值。3. Context 的取消與超時本文將探討 Go 語言中context的用法,從基

概述

在 Go 語言中,context(上下文)是一個非常重要的概念。Hm428資訊網——每日最新資訊28at.com

它主要用于在多個 goroutine 之間傳遞請求特定任務的截止日期、取消信號以及其他請求范圍的值。3. Context 的取消與超時Hm428資訊網——每日最新資訊28at.com

本文將探討 Go 語言中context的用法,從基礎概念到實際應用,將全面了解上下文的使用方法。Hm428資訊網——每日最新資訊28at.com

主要內容包括Hm428資訊網——每日最新資訊28at.com

什么是 Context(上下文)Hm428資訊網——每日最新資訊28at.com

Context 的基本用法:創建與傳遞Hm428資訊網——每日最新資訊28at.com

Context 的取消與超時Hm428資訊網——每日最新資訊28at.com

Context 的值傳遞Hm428資訊網——每日最新資訊28at.com

實際應用場景:HTTP 請求的 Context 使用Hm428資訊網——每日最新資訊28at.com

數據庫操作中的 Context 應用Hm428資訊網——每日最新資訊28at.com

自定義 Context 的實現Hm428資訊網——每日最新資訊28at.com

Context 的生命周期管理Hm428資訊網——每日最新資訊28at.com

Context 的注意事項Hm428資訊網——每日最新資訊28at.com

1. 什么是 Context(上下文)

在 Go 語言中,context(上下文)是一個接口,定義了四個方法:Deadline()、Done()、Err()和Value(key interface{})。Hm428資訊網——每日最新資訊28at.com

它主要用于在 goroutine 之間傳遞請求的截止日期、取消信號以及其他請求范圍的值。Hm428資訊網——每日最新資訊28at.com

2. Context 的基本用法:創建與傳遞

2.1 創建 Context

package mainimport (  "context"  "fmt")func main() {  // 創建一個空的Context  ctx := context.Background()  // 創建一個帶有取消信號的Context  _, cancel := context.WithCancel(ctx)  defer cancel() // 延遲調用cancel,確保在函數退出時取消Context  fmt.Println("Context創建成功")}

以上代碼演示了如何創建一個空的context和一個帶有取消信號的context。Hm428資訊網——每日最新資訊28at.com

使用context.WithCancel(parent)可以創建一個帶有取消信號的子context。Hm428資訊網——每日最新資訊28at.com

在調用cancel函數時,所有基于該context的操作都會收到取消信號。Hm428資訊網——每日最新資訊28at.com

2.2 傳遞 Context

package mainimport (  "context"  "fmt"  "time")func worker(ctx context.Context) {  for {    select {    case <-ctx.Done():      fmt.Println("收到取消信號,任務結束")      return    default:      fmt.Println("正在執行任務...")      time.Sleep(1 * time.Second)    }  }}func main() {  ctx := context.Background()  ctxWithCancel, cancel := context.WithCancel(ctx)  defer cancel()  go worker(ctxWithCancel)  time.Sleep(3 * time.Second)  cancel() // 發送取消信號  time.Sleep(1 * time.Second)}

在上面例子中,創建了一個帶有取消信號的context,并將它傳遞給一個 goroutine 中的任務。Hm428資訊網——每日最新資訊28at.com

調用cancel函數,可以發送取消信號,中斷任務的執行。Hm428資訊網——每日最新資訊28at.com

3.Context 的取消與超時

3.1 使用 Context 實現取消

package mainimport (  "context"  "fmt"  "time")func main() {  ctx := context.Background()  ctxWithCancel, cancel := context.WithCancel(ctx)  go func() {    select {    case <-ctxWithCancel.Done():      fmt.Println("收到取消信號,任務結束")    case <-time.After(2 * time.Second):      fmt.Println("任務完成")    }  }()  time.Sleep(1 * time.Second)    cancel() // 發送取消信號    time.Sleep(1 * time.Second)}

在這個例子中,使用time.After函數模擬一個長時間運行的任務。Hm428資訊網——每日最新資訊28at.com

如果任務在 2 秒內完成,就打印“任務完成”,否則在接收到取消信號后打印“收到取消信號,任務結束”。Hm428資訊網——每日最新資訊28at.com

3.2 使用 Context 實現超時控制

package mainimport (  "context"  "fmt"  "time")func main() {  ctx := context.Background()    ctxWithTimeout, cancel := context.WithTimeout(ctx, 2*time.Second)    defer cancel()  select {  case <-ctxWithTimeout.Done():    fmt.Println("超時,任務結束")  case <-time.After(1 * time.Second):    fmt.Println("任務完成")  }}

在上面例子中,使用context.WithTimeout(parent, duration)函數創建了一個在 2 秒后自動取消的contextHm428資訊網——每日最新資訊28at.com

如果任務在 1 秒內完成,就打印“任務完成”,否則在 2 秒后打印“超時,任務結束”。Hm428資訊網——每日最新資訊28at.com

4. Context 的值傳遞

4.1 使用 WithValue 傳遞值

package mainimport (  "context"  "fmt")type key stringfunc main() {  ctx := context.WithValue(context.Background(), key("name"), "Alice")  value := ctx.Value(key("name"))  fmt.Println("Name:", value)}

在上面例子中,使用context.WithValue(parent, key, value)函數在context中傳遞了一個鍵值對。Hm428資訊網——每日最新資訊28at.com

使用ctx.Value(key)函數可以獲取傳遞的值。Hm428資訊網——每日最新資訊28at.com

5. 實際應用場景:HTTP 請求的 Context 使用

5.1 使用 Context 處理 HTTP 請求

package mainimport (  "fmt"  "net/http"  "time")func handler(w http.ResponseWriter, r *http.Request) {  ctx := r.Context()  select {  case <-time.After(3 * time.Second):    fmt.Fprintln(w, "Hello, World!")  case <-ctx.Done():    err := ctx.Err()    fmt.Println("處理請求:", err)    http.Error(w, err.Error(), http.StatusInternalServerError)  }}func main() {  http.HandleFunc("/", handler)  http.ListenAndServe(":8080", nil)}

在上面例子中,使用http.Request結構體中的Context()方法獲取到請求的context,并在處理請求時設置了 3 秒的超時時間。Hm428資訊網——每日最新資訊28at.com

如果請求在 3 秒內完成,就返回“Hello, World!”,否則返回一個錯誤。Hm428資訊網——每日最新資訊28at.com

5.2 處理 HTTP 請求的超時與取消

package mainimport (  "context"  "fmt"  "net/http"  "time")func handler(w http.ResponseWriter, r *http.Request) {  ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)  defer cancel()  select {  case <-time.After(3 * time.Second):    fmt.Fprintln(w, "Hello, World!")  case <-ctx.Done():    err := ctx.Err()    fmt.Println("處理請求:", err)    http.Error(w, err.Error(), http.StatusInternalServerError)  }}func main() {  http.HandleFunc("/", handler)  http.ListenAndServe(":8080", nil)}

在上面例子中,使用context.WithTimeout(parent, duration)函數為每個請求設置了 2 秒的超時時間。Hm428資訊網——每日最新資訊28at.com

如果請求在 2 秒內完成,就返回“Hello, World!”,否則返回一個錯誤。Hm428資訊網——每日最新資訊28at.com

6. 數據庫操作中的 Context 應用

6.1 使用 Context 控制數據庫查詢的超時

package mainimport (  "context"  "database/sql"  "fmt"  "time"  _ "github.com/go-sql-driver/mysql")func main() {  db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database")    if err != nil {    fmt.Println(err)    return  }    defer db.Close()  ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)    defer cancel()  rows, err := db.QueryContext(ctx, "SELECT * FROM users")    if err != nil {    fmt.Println("查詢出錯:", err)    return  }    defer rows.Close()  // 處理查詢結果}

在上面例子中,使用context.WithTimeout(parent, duration)函數為數據庫查詢設置了 2 秒的超時時間,確保在 2 秒內完成查詢操作。Hm428資訊網——每日最新資訊28at.com

如果查詢超時,程序會收到context的取消信號,從而中斷數據庫查詢。Hm428資訊網——每日最新資訊28at.com

6.2 使用 Context 取消長時間運行的數據庫事務

package mainimport (  "context"  "database/sql"  "fmt"  "time"  _ "github.com/go-sql-driver/mysql")func main() {  db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database")    if err != nil {    fmt.Println(err)    return  }  defer db.Close()  tx, err := db.Begin()  if err != nil {    fmt.Println(err)    return  }  ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)    defer cancel()  go func() {    <-ctx.Done()        fmt.Println("接收到取消信號,回滾事務")        tx.Rollback()  }()  // 執行長時間運行的事務操作  // ...  err = tx.Commit()  if err != nil {      fmt.Println("提交事務出錯:", err)        return  }  fmt.Println("事務提交成功")}

在這個例子中,使用context.WithTimeout(parent, duration)函數為數據庫事務設置了 2 秒的超時時間。Hm428資訊網——每日最新資訊28at.com

同時使用 goroutine 監聽context的取消信號。Hm428資訊網——每日最新資訊28at.com

在 2 秒內事務沒有完成,程序會收到context的取消信號,從而回滾事務。Hm428資訊網——每日最新資訊28at.com

7. 自定義 Context 的實現

7.1 實現自定義的 Context 類型

package mainimport (  "context"  "fmt"  "time")type MyContext struct {  context.Context  RequestID string}func WithRequestID(ctx context.Context, requestID string) *MyContext {  return &MyContext{    Context:   ctx,    RequestID: requestID,  }}func (c *MyContext) Deadline() (deadline time.Time, ok bool) {  return c.Context.Deadline()}func (c *MyContext) Done() <-chan struct{} {  return c.Context.Done()}func (c *MyContext) Err() error {  return c.Context.Err()}func (c *MyContext) Value(key interface{}) interface{} {  if key == "requestID" {    return c.RequestID  }  return c.Context.Value(key)}func main() {  ctx := context.Background()    ctxWithRequestID := WithRequestID(ctx, "12345")  requestID := ctxWithRequestID.Value("requestID").(string)    fmt.Println("Request ID:", requestID)}

在這個例子中,實現了一個自定義的MyContext類型,它包含了一個RequestID字段。Hm428資訊網——每日最新資訊28at.com

通過WithRequestID函數,可以在原有的context上附加一個RequestID值,然后在需要的時候獲取這個值。Hm428資訊網——每日最新資訊28at.com

7.2 自定義 Context 的應用場景

自定義context類型的應用場景非常廣泛,比如在微服務架構中,Hm428資訊網——每日最新資訊28at.com

可在context中加入一些額外的信息,比如用戶 ID、請求來源等,以便在服務調用鏈路中傳遞這些信息。Hm428資訊網——每日最新資訊28at.com

8. Context 的生命周期管理

8.1 Context 的生命周期

context.Context 是不可變的,一旦創建就不能修改。它的值在傳遞時是安全的,可以被多個 goroutine 共享。Hm428資訊網——每日最新資訊28at.com

在一個請求處理的生命周期內,通常會創建一個頂級的 Context,然后從這個頂級的 Context 派生出子 Context,傳遞給具體的處理函數。Hm428資訊網——每日最新資訊28at.com

8.2 Context 的取消

當請求處理完成或者發生錯誤時,應該主動調用 context.WithCancel 或 context.WithTimeout 等函數創建的 Context 的 Cancel 函數來通知子 goroutines 停止工作。Hm428資訊網——每日最新資訊28at.com

這樣可以確保資源被及時釋放,避免 goroutine 泄漏。Hm428資訊網——每日最新資訊28at.com

func handleRequest(ctx context.Context) {    // 派生一個新的 Context,設置超時時間    ctx, cancel := context.WithTimeout(ctx, time.Second)        defer cancel() // 確保在函數退出時調用 cancel,防止資源泄漏    // 在這個新的 Context 下進行操作    // ...}

8.3 Context 的傳遞

在函數之間傳遞 Context 時,確保傳遞的是必要的最小信息。避免在函數間傳遞整個 Context,而是選擇傳遞 Context 的衍生物。Hm428資訊網——每日最新資訊28at.com

如 context.WithValue 創建的 Context,其中包含了特定的鍵值對信息。Hm428資訊網——每日最新資訊28at.com

func middleware(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {// 從請求中獲取特定的信息userID := extractUserID(r)// 將特定的信息存儲到 Context 中ctx := context.WithValue(r.Context(), userIDKey, userID)// 將新的 Context 傳遞給下一個處理器next.ServeHTTP(w, r.WithContext(ctx))})}

9. Context 的注意事項

9.1 不要在函數簽名中傳遞 Context

避免在函數的參數列表中傳遞 context.Context,除非確實需要用到它。Hm428資訊網——每日最新資訊28at.com

如果函數的邏輯只需要使用 Context 的部分功能,那么最好只傳遞它需要的具體信息,而不是整個 Context。Hm428資訊網——每日最新資訊28at.com

// 不推薦的做法func processRequest(ctx context.Context) {    // ...}// 推薦的做法func processRequest(userID int, timeout time.Duration) {    // 使用 userID 和 timeout,而不是整個 Context}

9.2 避免在結構體中濫用 Context

不要在結構體中保存 context.Context,因為它會增加結構體的復雜性。Hm428資訊網——每日最新資訊28at.com

若是需要在結構體中使用 Context 的值,最好將需要的值作為結構體的字段傳遞進來。Hm428資訊網——每日最新資訊28at.com

type MyStruct struct {    // 不推薦的做法    Ctx context.Context        // 推薦的做法    UserID int}

本文鏈接:http://www.tebozhan.com/showinfo-26-16279-0.htmlGo語言高級特性:Context深入解讀

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Spring事件機制,深入剖析,提升你的技術水平!

下一篇: Python 中的 IS 和 == 運算符有什么區別?

標簽:
  • 熱門焦點
  • 帥氣純真少年!日本最帥初中生選美冠軍出爐

    日本第一帥哥初一生選美大賽冠軍現已正式出爐,冠軍是來自千葉縣的宗田悠良。日本一直熱衷于各種選美大賽,從&ldquo;最美JK&rdquo;起到&ldquo;最美女星&r
  • 企業采用CRM系統的11個好處

    客戶關系管理(CRM)軟件可以為企業提供很多的好處,從客戶保留到提高生產力。  CRM軟件用于企業收集客戶互動,以改善客戶體驗和滿意度?! RM軟件市場規模如今超過580
  • 谷歌KDD'23工作:如何提升推薦系統Ranking模型訓練穩定性

    谷歌在KDD 2023發表了一篇工作,探索了推薦系統ranking模型的訓練穩定性問題,分析了造成訓練穩定性存在問題的潛在原因,以及現有的一些提升模型穩定性方法的不足,并提出了一種新
  • 2023年,我眼中的字節跳動

    此時此刻(2023年7月),字節跳動從未上市,也從未公布過任何官方的上市計劃;但是這并不妨礙它成為中國最受關注的互聯網公司之一。從2016-17年的抖音強勢崛起,到2018年的&ldquo;頭騰
  • 破圈是B站頭上的緊箍咒

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之每年的暑期檔都少不了瞄準追劇女孩們的古偶劇集,2021年有優酷的《山河令》,2022年有愛奇藝的《蒼蘭訣》,今年卻輪到小破站抓住了追
  • 自律,給不了Keep自由!

    來源 | 互聯網品牌官作者 | 李大為編排 | 又耳 審核 | 谷曉輝自律能不能給用戶自由暫時不好說,但大概率不能給Keep自由。近日,全球最大的在線健身平臺Keep正式登陸港交所,努力
  • 當家的盒馬,加速謀生

    來源 | 價值星球Planet作者 | 歸去來自己&ldquo;當家&rdquo;的盒馬,開始加速謀生了。據盒馬官微消息,盒馬計劃今年開放生鮮供應鏈,將其生鮮商品送往食堂。目前,盒馬在上海已經與
  • 2299元起!iQOO Pad開啟預售:性能最強天璣平板

    5月23日,iQOO如期舉行了新品發布會,除了首發安卓最強旗艦處理器的iQOO Neo8系列新機外,還在發布會上推出了旗下首款平板電腦——iQOO Pad,其搭載了天璣
  • “買真退假” 這種“羊毛”不能薅

    □ 法治日報 記者 王春   □ 本報通訊員 胡佳麗  2020年初,還在上大學的小東加入了一個大學生兼職QQ群。群主&ldquo;七王&rdquo;在群里介紹一些刷單賺
Top