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

當(dāng)前位置:首頁(yè) > 科技  > 軟件

Go語(yǔ)言高級(jí)特性:Context深入解讀

來(lái)源: 責(zé)編: 時(shí)間:2023-11-01 09:18:43 274觀看
導(dǎo)讀概述在 Go 語(yǔ)言中,context(上下文)是一個(gè)非常重要的概念。它主要用于在多個(gè) goroutine 之間傳遞請(qǐng)求特定任務(wù)的截止日期、取消信號(hào)以及其他請(qǐng)求范圍的值。3. Context 的取消與超時(shí)本文將探討 Go 語(yǔ)言中context的用法,從基

概述

在 Go 語(yǔ)言中,context(上下文)是一個(gè)非常重要的概念。cXs28資訊網(wǎng)——每日最新資訊28at.com

它主要用于在多個(gè) goroutine 之間傳遞請(qǐng)求特定任務(wù)的截止日期、取消信號(hào)以及其他請(qǐng)求范圍的值。3. Context 的取消與超時(shí)cXs28資訊網(wǎng)——每日最新資訊28at.com

本文將探討 Go 語(yǔ)言中context的用法,從基礎(chǔ)概念到實(shí)際應(yīng)用,將全面了解上下文的使用方法。cXs28資訊網(wǎng)——每日最新資訊28at.com

主要內(nèi)容包括cXs28資訊網(wǎng)——每日最新資訊28at.com

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

Context 的基本用法:創(chuàng)建與傳遞cXs28資訊網(wǎng)——每日最新資訊28at.com

Context 的取消與超時(shí)cXs28資訊網(wǎng)——每日最新資訊28at.com

Context 的值傳遞cXs28資訊網(wǎng)——每日最新資訊28at.com

實(shí)際應(yīng)用場(chǎng)景:HTTP 請(qǐng)求的 Context 使用cXs28資訊網(wǎng)——每日最新資訊28at.com

數(shù)據(jù)庫(kù)操作中的 Context 應(yīng)用cXs28資訊網(wǎng)——每日最新資訊28at.com

自定義 Context 的實(shí)現(xiàn)cXs28資訊網(wǎng)——每日最新資訊28at.com

Context 的生命周期管理cXs28資訊網(wǎng)——每日最新資訊28at.com

Context 的注意事項(xiàng)cXs28資訊網(wǎng)——每日最新資訊28at.com

1. 什么是 Context(上下文)

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

它主要用于在 goroutine 之間傳遞請(qǐng)求的截止日期、取消信號(hào)以及其他請(qǐng)求范圍的值。cXs28資訊網(wǎng)——每日最新資訊28at.com

2. Context 的基本用法:創(chuàng)建與傳遞

2.1 創(chuàng)建 Context

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

以上代碼演示了如何創(chuàng)建一個(gè)空的context和一個(gè)帶有取消信號(hào)的context。cXs28資訊網(wǎng)——每日最新資訊28at.com

使用context.WithCancel(parent)可以創(chuàng)建一個(gè)帶有取消信號(hào)的子context。cXs28資訊網(wǎng)——每日最新資訊28at.com

在調(diào)用cancel函數(shù)時(shí),所有基于該context的操作都會(huì)收到取消信號(hào)。cXs28資訊網(wǎng)——每日最新資訊28at.com

2.2 傳遞 Context

package mainimport (  "context"  "fmt"  "time")func worker(ctx context.Context) {  for {    select {    case <-ctx.Done():      fmt.Println("收到取消信號(hào),任務(wù)結(jié)束")      return    default:      fmt.Println("正在執(zhí)行任務(wù)...")      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() // 發(fā)送取消信號(hào)  time.Sleep(1 * time.Second)}

在上面例子中,創(chuàng)建了一個(gè)帶有取消信號(hào)的context,并將它傳遞給一個(gè) goroutine 中的任務(wù)。cXs28資訊網(wǎng)——每日最新資訊28at.com

調(diào)用cancel函數(shù),可以發(fā)送取消信號(hào),中斷任務(wù)的執(zhí)行。cXs28資訊網(wǎng)——每日最新資訊28at.com

3.Context 的取消與超時(shí)

3.1 使用 Context 實(shí)現(xiàn)取消

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

在這個(gè)例子中,使用time.After函數(shù)模擬一個(gè)長(zhǎng)時(shí)間運(yùn)行的任務(wù)。cXs28資訊網(wǎng)——每日最新資訊28at.com

如果任務(wù)在 2 秒內(nèi)完成,就打印“任務(wù)完成”,否則在接收到取消信號(hào)后打印“收到取消信號(hào),任務(wù)結(jié)束”。cXs28資訊網(wǎng)——每日最新資訊28at.com

3.2 使用 Context 實(shí)現(xiàn)超時(shí)控制

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("超時(shí),任務(wù)結(jié)束")  case <-time.After(1 * time.Second):    fmt.Println("任務(wù)完成")  }}

在上面例子中,使用context.WithTimeout(parent, duration)函數(shù)創(chuàng)建了一個(gè)在 2 秒后自動(dòng)取消的contextcXs28資訊網(wǎng)——每日最新資訊28at.com

如果任務(wù)在 1 秒內(nèi)完成,就打印“任務(wù)完成”,否則在 2 秒后打印“超時(shí),任務(wù)結(jié)束”。cXs28資訊網(wǎng)——每日最新資訊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)函數(shù)在context中傳遞了一個(gè)鍵值對(duì)。cXs28資訊網(wǎng)——每日最新資訊28at.com

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

5. 實(shí)際應(yīng)用場(chǎng)景:HTTP 請(qǐng)求的 Context 使用

5.1 使用 Context 處理 HTTP 請(qǐng)求

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("處理請(qǐng)求:", err)    http.Error(w, err.Error(), http.StatusInternalServerError)  }}func main() {  http.HandleFunc("/", handler)  http.ListenAndServe(":8080", nil)}

在上面例子中,使用http.Request結(jié)構(gòu)體中的Context()方法獲取到請(qǐng)求的context,并在處理請(qǐng)求時(shí)設(shè)置了 3 秒的超時(shí)時(shí)間。cXs28資訊網(wǎng)——每日最新資訊28at.com

如果請(qǐng)求在 3 秒內(nèi)完成,就返回“Hello, World!”,否則返回一個(gè)錯(cuò)誤。cXs28資訊網(wǎng)——每日最新資訊28at.com

5.2 處理 HTTP 請(qǐng)求的超時(shí)與取消

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("處理請(qǐng)求:", err)    http.Error(w, err.Error(), http.StatusInternalServerError)  }}func main() {  http.HandleFunc("/", handler)  http.ListenAndServe(":8080", nil)}

在上面例子中,使用context.WithTimeout(parent, duration)函數(shù)為每個(gè)請(qǐng)求設(shè)置了 2 秒的超時(shí)時(shí)間。cXs28資訊網(wǎng)——每日最新資訊28at.com

如果請(qǐng)求在 2 秒內(nèi)完成,就返回“Hello, World!”,否則返回一個(gè)錯(cuò)誤。cXs28資訊網(wǎng)——每日最新資訊28at.com

6. 數(shù)據(jù)庫(kù)操作中的 Context 應(yīng)用

6.1 使用 Context 控制數(shù)據(jù)庫(kù)查詢的超時(shí)

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("查詢出錯(cuò):", err)    return  }    defer rows.Close()  // 處理查詢結(jié)果}

在上面例子中,使用context.WithTimeout(parent, duration)函數(shù)為數(shù)據(jù)庫(kù)查詢?cè)O(shè)置了 2 秒的超時(shí)時(shí)間,確保在 2 秒內(nèi)完成查詢操作。cXs28資訊網(wǎng)——每日最新資訊28at.com

如果查詢超時(shí),程序會(huì)收到context的取消信號(hào),從而中斷數(shù)據(jù)庫(kù)查詢。cXs28資訊網(wǎng)——每日最新資訊28at.com

6.2 使用 Context 取消長(zhǎng)時(shí)間運(yùn)行的數(shù)據(jù)庫(kù)事務(wù)

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("接收到取消信號(hào),回滾事務(wù)")        tx.Rollback()  }()  // 執(zhí)行長(zhǎng)時(shí)間運(yùn)行的事務(wù)操作  // ...  err = tx.Commit()  if err != nil {      fmt.Println("提交事務(wù)出錯(cuò):", err)        return  }  fmt.Println("事務(wù)提交成功")}

在這個(gè)例子中,使用context.WithTimeout(parent, duration)函數(shù)為數(shù)據(jù)庫(kù)事務(wù)設(shè)置了 2 秒的超時(shí)時(shí)間。cXs28資訊網(wǎng)——每日最新資訊28at.com

同時(shí)使用 goroutine 監(jiān)聽(tīng)context的取消信號(hào)。cXs28資訊網(wǎng)——每日最新資訊28at.com

在 2 秒內(nèi)事務(wù)沒(méi)有完成,程序會(huì)收到context的取消信號(hào),從而回滾事務(wù)。cXs28資訊網(wǎng)——每日最新資訊28at.com

7. 自定義 Context 的實(shí)現(xiàn)

7.1 實(shí)現(xiàn)自定義的 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)}

在這個(gè)例子中,實(shí)現(xiàn)了一個(gè)自定義的MyContext類型,它包含了一個(gè)RequestID字段。cXs28資訊網(wǎng)——每日最新資訊28at.com

通過(guò)WithRequestID函數(shù),可以在原有的context上附加一個(gè)RequestID值,然后在需要的時(shí)候獲取這個(gè)值。cXs28資訊網(wǎng)——每日最新資訊28at.com

7.2 自定義 Context 的應(yīng)用場(chǎng)景

自定義context類型的應(yīng)用場(chǎng)景非常廣泛,比如在微服務(wù)架構(gòu)中,cXs28資訊網(wǎng)——每日最新資訊28at.com

可在context中加入一些額外的信息,比如用戶 ID、請(qǐng)求來(lái)源等,以便在服務(wù)調(diào)用鏈路中傳遞這些信息。cXs28資訊網(wǎng)——每日最新資訊28at.com

8. Context 的生命周期管理

8.1 Context 的生命周期

context.Context 是不可變的,一旦創(chuàng)建就不能修改。它的值在傳遞時(shí)是安全的,可以被多個(gè) goroutine 共享。cXs28資訊網(wǎng)——每日最新資訊28at.com

在一個(gè)請(qǐng)求處理的生命周期內(nèi),通常會(huì)創(chuàng)建一個(gè)頂級(jí)的 Context,然后從這個(gè)頂級(jí)的 Context 派生出子 Context,傳遞給具體的處理函數(shù)。cXs28資訊網(wǎng)——每日最新資訊28at.com

8.2 Context 的取消

當(dāng)請(qǐng)求處理完成或者發(fā)生錯(cuò)誤時(shí),應(yīng)該主動(dòng)調(diào)用 context.WithCancel 或 context.WithTimeout 等函數(shù)創(chuàng)建的 Context 的 Cancel 函數(shù)來(lái)通知子 goroutines 停止工作。cXs28資訊網(wǎng)——每日最新資訊28at.com

這樣可以確保資源被及時(shí)釋放,避免 goroutine 泄漏。cXs28資訊網(wǎng)——每日最新資訊28at.com

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

8.3 Context 的傳遞

在函數(shù)之間傳遞 Context 時(shí),確保傳遞的是必要的最小信息。避免在函數(shù)間傳遞整個(gè) Context,而是選擇傳遞 Context 的衍生物。cXs28資訊網(wǎng)——每日最新資訊28at.com

如 context.WithValue 創(chuàng)建的 Context,其中包含了特定的鍵值對(duì)信息。cXs28資訊網(wǎng)——每日最新資訊28at.com

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

9. Context 的注意事項(xiàng)

9.1 不要在函數(shù)簽名中傳遞 Context

避免在函數(shù)的參數(shù)列表中傳遞 context.Context,除非確實(shí)需要用到它。cXs28資訊網(wǎng)——每日最新資訊28at.com

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

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

9.2 避免在結(jié)構(gòu)體中濫用 Context

不要在結(jié)構(gòu)體中保存 context.Context,因?yàn)樗鼤?huì)增加結(jié)構(gòu)體的復(fù)雜性。cXs28資訊網(wǎng)——每日最新資訊28at.com

若是需要在結(jié)構(gòu)體中使用 Context 的值,最好將需要的值作為結(jié)構(gòu)體的字段傳遞進(jìn)來(lái)。cXs28資訊網(wǎng)——每日最新資訊28at.com

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

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

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: Spring事件機(jī)制,深入剖析,提升你的技術(shù)水平!

下一篇: Python 中的 IS 和 == 運(yùn)算符有什么區(qū)別?

標(biāo)簽:
  • 熱門焦點(diǎn)
Top