国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Go語言Context應(yīng)用全攻略:異步編程利器

開發(fā) 前端
在 Go 語言中,Context(上下文)是一個非常重要的概念,特別是在處理請求時。允許在請求的整個生命周期內(nèi)傳遞數(shù)據(jù)、控制請求的取消、處理超時等。本文將介紹 Go 語言中 Context 的使用,幫助更好地理解與處理請求的傳遞與控制。

概述

在 Go 語言中,Context(上下文)是一個非常重要的概念,特別是在處理請求時。

允許在請求的整個生命周期內(nèi)傳遞數(shù)據(jù)、控制請求的取消、處理超時等。

本文將介紹 Go 語言中 Context 的使用,幫助更好地理解與處理請求的傳遞與控制。

主要內(nèi)容包括

Context 基礎(chǔ)

Context 創(chuàng)建與傳遞

Context 的超時與取消

Context 的鏈?zhǔn)讲僮?/p>

Context 在并發(fā)中的應(yīng)用

Context 的應(yīng)用場景

最佳實踐與注意事項

1. Context 基礎(chǔ)

在 Go 語言中,context.Context 接口定義了一個請求的上下文。

它包含了請求的截止時間、取消信號和請求的數(shù)據(jù)。

使用 Context 可以在請求之間有效地傳遞數(shù)據(jù),同時也可以控制請求的生命周期。

type Context interface {


Deadline() (deadline time.Time, ok bool)


Done() <-chan struct{}


Err() error


Value(key interface{}) interface{}
}

Context 接口包含了四個方法:Deadline() 返回 Context 的截止時間

Done() 返回一個通道,它會在 Context 被取消或超時時關(guān)閉

Err() 返回 Context 的錯誤信息,Value(key) 返回 Context 中與 key 關(guān)聯(lián)的值。

2. Context 創(chuàng)建與傳遞

2.1 創(chuàng)建和傳遞 Context

package main


import (
  "context"
  "fmt"
  "time"
)


func main() {
  // 創(chuàng)建一個根Context
  rootContext := context.Background()


  // 創(chuàng)建一個帶有超時時間的Context,這里設(shè)置超時時間為2秒
  ctx, cancel := context.WithTimeout(rootContext, 2*time.Second)
  defer cancel()


  // 在新的goroutine中執(zhí)行任務(wù)
  go func(ctx context.Context) {
    select {
    case <-time.After(3 * time.Second):
      fmt.Println("任務(wù)完成")
    case <-ctx.Done():
      fmt.Println("任務(wù)取消或超時")
    }
  }(ctx)
  
  // 等待一段時間,模擬程序運行
  time.Sleep(5 * time.Second)
}

在這個例子中,創(chuàng)建了一個帶有 2 秒超時時間的 Context,并在一個新的 goroutine 中執(zhí)行一個任務(wù)。

在主 goroutine 中,等待了 5 秒,因此任務(wù)在超時之前完成,所以會輸出"任務(wù)完成"。

2.2 使用 WithValue 傳遞數(shù)據(jù)

package main


import (
  "context"
  "fmt"
)


type key string


func main() {
  // 創(chuàng)建一個根Context
  rootContext := context.Background()


  // 使用WithValue傳遞數(shù)據(jù)
  ctx := context.WithValue(rootContext, key("userID"), 123)


  // 在子函數(shù)中獲取傳遞的數(shù)據(jù)
  getUserID(ctx)
}


func getUserID(ctx context.Context) {
  // 從Context中獲取數(shù)據(jù)
  if userID, ok := ctx.Value(key("userID")).(int); ok {
    fmt.Println("UserID:", userID)
  } else {
    fmt.Println("UserID不存在")
  }
}

在這個示例中,使用 WithValue 方法在 Context 中傳遞了一個 userID 的值,并在 getUserID 函數(shù)中成功獲取并打印了這個值。

3. Context 的超時與取消

3.1 設(shè)置請求超時時間

package main


import (
  "context"
  "fmt"
  "time"
)


func main() {
  // 創(chuàng)建一個根Context
  rootContext := context.Background()


  // 創(chuàng)建一個超時時間為2秒的Context
  timeoutCtx, _ := context.WithTimeout(rootContext, 2*time.Second)


  // 創(chuàng)建一個手動取消的Context
  cancelCtx, cancel := context.WithCancel(rootContext)
  defer cancel()


  // 在新的goroutine中執(zhí)行任務(wù)
  go func(ctx context.Context) {
    select {
    case <-time.After(3 * time.Second):
      fmt.Println("任務(wù)完成")
    case <-ctx.Done():
      fmt.Println("任務(wù)取消或超時")
    }
  }(timeoutCtx)


  // 在另一個goroutine中執(zhí)行任務(wù)
  go func(ctx context.Context) {
    select {
    case <-time.After(1 * time.Second):
      fmt.Println("另一個任務(wù)完成")
    case <-ctx.Done():
      fmt.Println("另一個任務(wù)取消")
    }
  }(cancelCtx)


  // 等待一段時間,模擬程序運行
  time.Sleep(5 * time.Second)
}

在上面例子中,用 WithTimeout 方法創(chuàng)建了一個帶有 2 秒超時時間的 Context。

在任務(wù)的 goroutine 中,用 select 語句監(jiān)聽了超時和 Context 的取消兩個事件,以便及時響應(yīng)。

3.2 處理請求取消

package main


import (
  "context"
  "fmt"
  "time"
)


func main() {
  // 創(chuàng)建一個根Context
  rootContext := context.Background()


  // 創(chuàng)建一個可以手動取消的Context
  ctx, cancel := context.WithCancel(rootContext)
  defer cancel()


  // 在新的goroutine中執(zhí)行任務(wù)
  go func(ctx context.Context) {
    select {
    case <-time.After(3 * time.Second):
      fmt.Println("任務(wù)完成")
    case <-ctx.Done():
      fmt.Println("任務(wù)取消")
    }
  }(ctx)


  // 等待一段時間,手動取消任務(wù)
  time.Sleep(2 * time.Second)
  cancel()


  // 等待一段時間,模擬程序運行
  time.Sleep(1 * time.Second)
}

在上面例子中,使用 WithCancel 方法創(chuàng)建了一個可以手動取消的 Context。

在主函數(shù)中,等待了 2 秒后,手動調(diào)用 cancel 函數(shù)取消了任務(wù)。

這時,在任務(wù)的 goroutine 中,ctx.Done() 會接收到取消信號,從而退出任務(wù)。

4. Context 的鏈?zhǔn)讲僮?/h2>

在實際應(yīng)用中,可能需要將多個 Context 串聯(lián)起來使用。

Go 語言的 Context 提供了 WithCancel、WithDeadline、WithTimeout 等方法。

可以用這些方法實現(xiàn)多個 Context 的協(xié)同工作。

package main


import (
  "context"
  "fmt"
  "time"
)


func main() {
  // 創(chuàng)建一個根Context
  rootContext := context.Background()


  // 創(chuàng)建一個超時時間為2秒的Context
  timeoutCtx, _ := context.WithTimeout(rootContext, 2*time.Second)


  // 創(chuàng)建一個手動取消的Context
  cancelCtx, cancel := context.WithCancel(rootContext)
  defer cancel()


  // 在新的goroutine中執(zhí)行任務(wù)
  go func(ctx context.Context) {
    select {
    case <-time.After(3 * time.Second):
      fmt.Println("任務(wù)完成")
    case <-ctx.Done():
      fmt.Println("任務(wù)取消或超時")
    }
  }(timeoutCtx)


  // 在另一個goroutine中執(zhí)行任務(wù)
  go func(ctx context.Context) {
    select {
    case <-time.After(1 * time.Second):
      fmt.Println("另一個任務(wù)完成")
    case <-ctx.Done():
      fmt.Println("另一個任務(wù)取消")
    }
  }(cancelCtx)


  // 等待一段時間,模擬程序運行
  time.Sleep(5 * time.Second)
}

在示例中,創(chuàng)建了一個帶有 2 秒超時時間的 Context 和一個可以手動取消的 Context,然后分別傳遞給兩個不同的任務(wù)。

在主函數(shù)中,等待了 5 秒,超時時間為 2 秒,因此第一個任務(wù)會因超時而取消,第二個任務(wù)則會在 1 秒后完成。

5. Context 在并發(fā)中的應(yīng)用

5.1 使用 Context 控制多個協(xié)程

package main


import (
  "context"
  "fmt"
  "sync"
  "time"
)


func main() {
  // 創(chuàng)建一個根Context
  rootContext := context.Background()


  // 創(chuàng)建一個可以手動取消的Context
  ctx, cancel := context.WithCancel(rootContext)
  defer cancel()


  // 使用WaitGroup等待所有任務(wù)完成
  var wg sync.WaitGroup


  // 啟動多個協(xié)程執(zhí)行任務(wù)
  for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(id int) {
      defer wg.Done()
      select {
      case <-time.After(time.Duration(id) * time.Second):
        fmt.Println("任務(wù)", id, "完成")
      case <-ctx.Done():
        fmt.Println("任務(wù)", id, "取消")
      }
    }(i)
  }


  // 等待一段時間,然后手動取消任務(wù)
  time.Sleep(2 * time.Second)
  cancel()


  // 等待所有任務(wù)完成
  wg.Wait()
}

在上面例子中,創(chuàng)建了一個可以手動取消的 Context,并使用 sync.WaitGroup 等待所有任務(wù)完成。

在 for 循環(huán)中,啟動了 5 個協(xié)程,每個協(xié)程會等待一段時間后輸出任務(wù)完成信息。

在主函數(shù)中,程序等待了 2 秒后,手動調(diào)用 cancel 函數(shù)取消了任務(wù),協(xié)程會接收到取消信號并退出。

5.2 避免 Context 濫用

在使用 Context 時,要避免將 Context 放在結(jié)構(gòu)體中。

因為 Context 應(yīng)該作為函數(shù)參數(shù)傳遞,而不應(yīng)該被放在結(jié)構(gòu)體中進(jìn)行傳遞。

Context 應(yīng)該限定在程序的最小作用域,不要傳遞到不需要它的函數(shù)中。

6. Context 的應(yīng)用場景

6.1 HTTP 請求中的 Context 使用

package main


import (
  "fmt"
  "net/http"
  "time"
)


func handler(w http.ResponseWriter, r *http.Request) {
  ctx := r.Context()


  select {
  case <-time.After(2 * time.Second):
    fmt.Fprintln(w, "Hello, World!")
  case <-ctx.Done():
    err := ctx.Err()
    fmt.Println("Server:", err)
    http.Error(w, err.Error(), http.StatusInternalServerError)
  }
}


func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":8080", nil)
}

在上面示例中,創(chuàng)建了一個 HTTP 請求處理函數(shù) handler。

在處理函數(shù)中,用 r.Context() 獲取到請求的 Context,并在其中執(zhí)行一個耗時的任務(wù)。

如果請求超時,ctx.Done() 會接收到取消信號,可以在其中處理請求超時的邏輯。

6.2 數(shù)據(jù)庫操作中的 Context 使用

package main


import (
  "context"
  "database/sql"
  "fmt"
  "time"


  _ "github.com/go-sql-driver/mysql"
)


func main() {
  // 連接數(shù)據(jù)庫
  db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database")
  if err != nil {
    fmt.Println("數(shù)據(jù)庫連接失敗:", err)
    return
  }
  defer db.Close()


  // 創(chuàng)建一個Context,設(shè)置超時時間為5秒
  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  defer cancel()


  // 在Context的超時時間內(nèi)執(zhí)行數(shù)據(jù)庫查詢
  rows, err := db.QueryContext(ctx, "SELECT * FROM users")
  if err != nil {
    fmt.Println("數(shù)據(jù)庫查詢失敗:", err)
    return
  }
  defer rows.Close()


  // 處理查詢結(jié)果
  for rows.Next() {
    // 處理每一行數(shù)據(jù)
  }
}

在上面例子中,使用 database/sql 包進(jìn)行數(shù)據(jù)庫查詢。創(chuàng)建了一個帶有 5 秒超時時間的 Context,并在其中執(zhí)行數(shù)據(jù)庫查詢。

如果查詢時間超過 5 秒,Context 會接收到取消信號,可以在其中執(zhí)行處理查詢超時的邏輯。

6.3 其他業(yè)務(wù)場景中的 Context 使用

在其他業(yè)務(wù)場景中,可使用 Context 實現(xiàn)更多復(fù)雜的任務(wù)協(xié)同。

例如,使用 Context 在多個微服務(wù)之間進(jìn)行數(shù)據(jù)傳遞和超時控制。

以下是一個示例,演示了如何在微服務(wù)架構(gòu)中使用 Context 進(jìn)行跨服務(wù)的數(shù)據(jù)傳遞

package main


import (
  "context"
  "fmt"
  "time"
)


type Request struct {
  ID int
}


type Response struct {
  Message string
}


func microservice(ctx context.Context, reqCh chan Request, resCh chan Response) {
  for {
    select {
    case <-ctx.Done():
      fmt.Println("Microservice shutting down...")
      return
    case req := <-reqCh:
      // 模擬處理請求的耗時操作
      time.Sleep(2 * time.Second)
      response := Response{Message: fmt.Sprintf("Processed request with ID %d", req.ID)}
      resCh <- response
    }
  }
}


func main() {
  // 創(chuàng)建根Context
  rootContext := context.Background()


  // 創(chuàng)建用于請求和響應(yīng)的通道
  reqCh := make(chan Request)
  resCh := make(chan Response)


  // 啟動微服務(wù)
  go microservice(rootContext, reqCh, resCh)


  // 創(chuàng)建帶有5秒超時時間的Context
  ctx, cancel := context.WithTimeout(rootContext, 5*time.Second)
  defer cancel()


  // 發(fā)送請求到微服務(wù)
  for i := 1; i <= 3; i++ {
    req := Request{ID: i}
    reqCh <- req


    select {
    case <-ctx.Done():
      fmt.Println("Request timed out!")
      return
    case res := <-resCh:
      fmt.Println(res.Message)
    }
  }
}

在上面示例中,創(chuàng)建了一個簡單的微服務(wù)模擬,它接收來自 reqCh 通道的請求,并將處理結(jié)果發(fā)送到 resCh 通道。

在主函數(shù)中,用帶有 5 秒超時時間的 Context 來確保請求不會無限期等待,同時也能夠處理超時的情況。

7. 最佳實踐與注意事項

7.1 避免在函數(shù)庫中使用 Context

通常情況下,應(yīng)該在函數(shù)的參數(shù)列表中顯式傳遞 Context,而不是將 Context 放在結(jié)構(gòu)體中。

這樣做可以使函數(shù)的行為更加明確,避免隱藏傳遞的 Context,提高代碼的可讀性和可維護(hù)性。

7.2 避免在結(jié)構(gòu)體中嵌入 Context

盡管可以將 Context 作為結(jié)構(gòu)體的成員嵌入,但這樣的做法通常是不推薦的。

因為 Context 應(yīng)該是在函數(shù)調(diào)用的時候傳遞,而不是嵌入在結(jié)構(gòu)體中。

如果結(jié)構(gòu)體的方法需要使用 Context,應(yīng)該將 Context 作為參數(shù)傳遞給這些方法。

7.3 注意 Context 的傳遞路徑

在實際應(yīng)用中,要仔細(xì)考慮 Context 的傳遞路徑。

若是在多個函數(shù)之間傳遞 Context,確保 Context 的傳遞路徑清晰明了,避免出現(xiàn)歧義和混亂。

Context 的傳遞路徑應(yīng)該盡量短,不要跨越過多的函數(shù)調(diào)用。

總結(jié)

在 Go 語言中,Context 是一個強(qiáng)大的工具,用于處理請求的傳遞、控制和超時等。

通過合理地使用 Context,可以編寫出更加穩(wěn)定、高效的異步程序,提高系統(tǒng)的健壯性和可維護(hù)性。

責(zé)任編輯:武曉燕 來源: Go先鋒
相關(guān)推薦

2023-10-13 19:42:00

2017-07-06 17:39:53

JavaScript開發(fā)程序員

2009-02-12 10:12:00

NAT配置

2010-11-18 23:24:42

云遷移

2009-02-10 09:47:00

應(yīng)用程序訪問權(quán)限

2024-05-07 09:01:21

Queue 模塊Python線程安全隊列

2013-04-15 10:48:16

Xcode ARC詳解iOS ARC使用

2013-06-08 11:13:00

Android開發(fā)XML解析

2010-04-23 14:04:23

Oracle日期操作

2014-03-19 17:22:33

2009-10-19 15:20:01

家庭綜合布線

2009-12-14 14:32:38

動態(tài)路由配置

2009-02-20 11:43:22

UNIXfish全攻略

2013-09-09 15:05:12

iOS應(yīng)用內(nèi)置付費IAP完全攻略

2019-06-27 11:47:21

Wordpress容器化HTTPS

2024-10-25 15:25:42

2020-11-23 15:21:12

Linux環(huán)境變量

2009-12-17 16:15:00

CCNA640-810

2009-07-17 17:43:49

Jruby開發(fā)Web

2009-11-10 12:08:15

點贊
收藏

51CTO技術(shù)棧公眾號

香蕉视频免费在线播放| 精品噜噜噜噜久久久久久久久试看| 欧美性猛交xxxx免费看漫画| www黄色av| 精品72久久久久中文字幕| 亚洲成成品网站| 4480yy私人影院高清不卡| 精品在线亚洲视频| 亚洲a在线播放| 欧美一级大片在线视频| 精品久久久久99| 亚洲kkk444kkk在线观看| 久久九九影视网| 法国空姐在线观看免费| 好吊日精品视频| 国产精品高潮呻吟久久av野狼 | 国产亚洲欧美一区二区| 久久97视频| 欧美成人全部免费| 欧亚av在线| 日韩欧美中文字幕精品| 男同在线观看| 夜夜嗨av一区二区三区| 少妇激情一区二区三区| 风流少妇一区二区| 99热一区二区三区| 日本va欧美va精品| 人偷久久久久久久偷女厕| 亚洲二区精品| 国产精品中出一区二区三区| 综合久久99| 99在线观看| 黄色av一区| 国产在线精品一区二区三区》| 欧美日韩精品| 国产美女在线精品免费观看| 午夜国产精品视频| 国产精品伊人日日| 亚洲欧美日韩国产综合精品二区 | 夜鲁很鲁在线视频| 午夜久久电影网| 亚洲欧美一区二区三区在线播放| 亚洲综合色噜噜狠狠| 淫视频在线观看| 亚洲香蕉伊在人在线观| 橘梨纱av一区二区三区在线观看| 亚洲天天做日日做天天谢日日欢| 激情亚洲综合网| 亚洲狠狠爱一区二区三区| 中文在线中文字幕| 欧洲生活片亚洲生活在线观看| 福利视频在线导航| 欧美体内she精视频| 在线免费观看污| 亚洲欧美日韩国产中文专区| 欧美伊人亚洲伊人色综合动图| 久久99热这里只有精品国产| 丝袜av一区| 99国产超薄肉色丝袜交足的后果 | 日本中文字幕高清视频| 亚洲成人精品影院| 国产在线观看黄| 欧美成人精品福利| 日本少妇一区| 高清一区二区三区四区五区| 一区二区美女| 精品日本一区二区三区| 国产精品99久久久久久似苏梦涵| 毛片av免费在线观看| 亚洲最新在线观看| 在线视频婷婷| 在线视频精品一| 欧美激情在线精品一区二区三区| 高清视频在线观看一区| 国产一区二区免费视频| 91色国产在线| 91福利小视频| 成人性生交大片免费网站 | 久热国产在线| 中文字幕国产亚洲| 国产在线播放精品| 91在线免费观看网站| 免费观看30秒视频久久| 国产天堂在线播放| 欧美日韩国产综合视频在线观看中文| 高h视频在线观看| 北条麻妃久久精品| 欧美一区成人| 成人免费毛片在线观看| 午夜久久电影网| 欧美magnet| 国产精品永久免费| 精品一区二区三区免费视频| 电影天堂久久| 日韩欧美高清一区| 色狼人综合干| 国产又黄又爽免费视频| 亚洲国产精品一区二区久久恐怖片 | 久久精品ww人人做人人爽| 国产成人免费视频一区| 91午夜在线| 亚洲国产天堂久久国产91| 成人资源在线| 日韩高清国产一区在线观看| 国产精品女同互慰在线看| 污污的网站在线看| 日本欧美一二三区| 国产资源在线一区| 一本大道香蕉久在线播放29| 亚洲少妇中文在线| 综合天天久久| 18成人免费观看视频漫画| 日韩成人xxxx| 欧美激情麻豆| 成人免费xx| 亚洲性猛交xxxxwww| 欧美日韩视频| 国产美女免费观看| 在线成人激情黄色| 国产九九精品| igao视频网在线视频| 久久亚洲成人精品| 日韩黄色小视频| 日韩欧美亚洲系列| 2019中文字幕在线观看| 懂色av一区二区三区蜜臀| 国产精品剧情| 91黄在线观看| 亚洲精品伦理在线| 大奶在线精品| 国产中文字幕视频在线观看| 精品国产乱码久久久久久老虎 | 中文在线资源观看视频网站免费不卡| 亚洲全部视频| 最近中文视频在线| 久久男人av资源网站| 国产在线播放一区三区四| 成人18在线| 99c视频在线| 亚洲国产另类av| 天堂av一区二区三区在线播放| 国产免费成人在线| 中文字幕成人精品久久不卡| 国产乱码精品一区二区三| 色噜噜狠狠狠综合欧洲色8| 国产欧美日韩综合精品二区| 欧美性猛xxx| 中文乱码免费一区二区三区下载| 成色在线视频| 国产成人一区二| 亚洲精品第1页| 精品国产成人| www浪潮av99com| 久久久久久久久久久亚洲| 成人美女在线观看| 男人添女人下部高潮视频在线观看 | 欧美精品久久久久久久久老牛影院| 日韩在线精品| 中文资源在线网| 999在线观看免费大全电视剧| 欧美日韩亚洲激情| 国产精品红桃| 亚洲91av| 国产高清免费在线| 在线观看视频99| 久久婷婷久久一区二区三区| av一区在线播放| 久草热视频在线观看| 欧美激情aaaa| 亚洲精品成a人| av影片在线一区| 国产成人天天5g影院在线观看| 国产精品一区二区不卡视频| 欧美日韩亚洲综合一区| 欧美激情成人在线| av片在线观看网站| 亚洲成人午夜在线| 亚洲视频axxx| 久久综合av免费| 成功精品影院| 在线免费观看高清视频色| 99在线高清视频在线播放| 欧美成va人片在线观看| 老汉av免费一区二区三区| 91亚洲视频| 黄色网址三级| 国产欧美一区二区在线播放| 亚洲国产精品久久精品怡红院| 风流少妇一区二区| 北条麻妃在线一区二区免费播放 | 91视频婷婷| 日韩一级在线观看| 波多野结衣亚洲一区| 欧美高清视频看片在线观看| 毛片免费在线| 国产91在线亚洲| 国产精品视频1区| 亚洲第一福利网站| 国产精品―色哟哟| 制服诱惑一区二区|