前言
編碼中遇到上下文信息傳遞,并發(fā)信息取消等,記錄下在go語言中context包的使用。
context 介紹
在Go語言中,context包提供了一種在程序中傳遞截止日期、取消信號、請求范圍數(shù)據(jù)和其他元數(shù)據(jù)的方式。context包的核心類型是Context接口,它定義了在執(zhí)行上下文中傳遞的方法。Context接口的主要方法包括Deadline、Done、Err、Value等。
關(guān)鍵概念和使用方式
-
Background:
context.Background()
函數(shù)返回一個空的Context
,通常作為整個應(yīng)用的頂層上下文,用于傳遞全局的信息。 -
WithCancel:
context.WithCancel
函數(shù)創(chuàng)建一個帶有取消信號的Context
。當(dāng)調(diào)用返回的cancel
函數(shù)時,與該Context
相關(guān)聯(lián)的所有操作都會被取消。ctx, cancel := context.WithCancel(context.Background()) defer cancel() // 在不再需要時調(diào)用cancel
-
WithTimeout和WithDeadline:
context.WithTimeout
和context.WithDeadline
函數(shù)創(chuàng)建帶有截止日期的Context
。WithTimeout
設(shè)置相對于當(dāng)前時間的截止日期,而WithDeadline
設(shè)置絕對時間的截止日期。ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() // 在不再需要時調(diào)用cancel
-
WithValue:
context.WithValue
函數(shù)可以在Context
中存儲鍵值對,用于傳遞請求范圍的數(shù)據(jù)。但要注意,過度使用WithValue
可能導(dǎo)致上下文變得復(fù)雜,應(yīng)慎重使用。ctx := context.WithValue(context.Background(), key, value)
-
Done和Err:
Done
通道會在上下文被取消或達(dá)到截止日期時關(guān)閉。Err
方法返回取消的原因,通常是context.Canceled
或context.DeadlineExceeded
。select { case <-ctx.Done(): // 上下文被取消 fmt.Println("Context canceled:", ctx.Err()) }
context
包的設(shè)計(jì)旨在簡化在不同部分之間傳遞截止日期、取消信號和請求范圍數(shù)據(jù)的方式,特別是在并發(fā)環(huán)境中。使用context
包可以更好地管理資源、控制執(zhí)行時間和處理取消操作。
基礎(chǔ)使用
基礎(chǔ)的context
包使用示例,演示如何創(chuàng)建上下文、設(shè)置截止日期、取消上下文等基本操作:
package main
import (
"context"
"fmt"
"time"
)
func main() {
// 創(chuàng)建一個帶有取消信號的上下文
ctx, cancel := context.WithCancel(context.Background())
// 啟動一個goroutine執(zhí)行任務(wù),并傳入上下文
go performTask(ctx)
// 模擬等待用戶輸入或其他觸發(fā)條件
fmt.Println("Press Enter to cancel the task.")
fmt.Scanln()
// 調(diào)用cancel函數(shù)取消上下文
cancel()
// 等待一段時間,以確保goroutine有足夠的時間處理取消操作
time.Sleep(time.Second * 2)
}
func performTask(ctx context.Context) {
// 使用select監(jiān)聽上下文的取消信號
select {
case <-ctx.Done():
// 當(dāng)上下文被取消時執(zhí)行的操作
fmt.Println("Task canceled:", ctx.Err())
default:
// 模擬一個長時間運(yùn)行的任務(wù)
for i := 1; i <= 5; i++ {
fmt.Println("Task is running...")
time.Sleep(time.Second)
}
fmt.Println("Task completed successfully.")
}
}
在這個示例中,我們首先創(chuàng)建一個帶有取消信號的上下文,然后啟動一個goroutine執(zhí)行performTask
函數(shù)。用戶在控制臺輸入任意字符后,我們調(diào)用cancel
函數(shù)取消上下文。performTask
函數(shù)中使用select
監(jiān)聽上下文的取消信號,一旦上下文被取消,任務(wù)將提前結(jié)束。在實(shí)際應(yīng)用中,可以根據(jù)需要設(shè)置截止日期、傳遞數(shù)據(jù)等,以更靈活地管理上下文。
進(jìn)階使用
進(jìn)階的復(fù)雜示例,演示如何使用context
包處理多個并發(fā)任務(wù),并在某個任務(wù)失敗或超時時取消所有任務(wù):
package main
import (
"context"
"fmt"
"math/rand"
"sync"
"time"
)
func main() {
// 創(chuàng)建一個帶有取消信號的上下文,設(shè)置總體超時為5秒
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
// 使用WaitGroup等待所有任務(wù)完成
var wg sync.WaitGroup
// 啟動多個goroutine執(zhí)行任務(wù)
for i := 1; i <= 3; i++ {
wg.Add(1)
go performTask(ctx, i, &wg)
}
// 等待所有任務(wù)完成或上下文取消
wg.Wait()
fmt.Println("All tasks completed.")
}
func performTask(ctx context.Context, taskID int, wg *sync.WaitGroup) {
defer wg.Done()
// 模擬每個任務(wù)的執(zhí)行時間
taskDuration := time.Second * time.Duration(rand.Intn(10))
fmt.Printf("Task %d started. Duration: %s\n", taskID, taskDuration)
// 使用WithTimeout創(chuàng)建一個子上下文,設(shè)置每個任務(wù)的超時時間
subCtx, cancel := context.WithTimeout(ctx, taskDuration)
defer cancel()
select {
case <-subCtx.Done():
// 當(dāng)子上下文被取消時執(zhí)行的操作
if subCtx.Err() == context.DeadlineExceeded {
fmt.Printf("Task %d timed out.\n", taskID)
} else {
fmt.Printf("Task %d canceled.\n", taskID)
}
case <-time.After(taskDuration):
// 模擬任務(wù)的實(shí)際工作
fmt.Printf("Task %d completed successfully.\n", taskID)
}
}
在這個示例中,我們創(chuàng)建了一個帶有總體超時的上下文,并啟動了多個goroutine執(zhí)行performTask
函數(shù)。每個任務(wù)都有一個隨機(jī)的執(zhí)行時間,并在子上下文中設(shè)置了超時。使用select
監(jiān)聽子上下文的取消信號,一旦有任務(wù)失敗或超時,它將及時結(jié)束。通過使用sync.WaitGroup
等待所有任務(wù)完成,我們確保在所有任務(wù)完成或總體超時后程序可以退出。文章來源:http://www.zghlxwxcb.cn/news/detail-813033.html
這種方式可以更好地控制并發(fā)任務(wù),確保及時釋放資源并在需要時取消任務(wù)。在實(shí)際應(yīng)用中,可以根據(jù)具體需求調(diào)整超時時間和處理邏輯。文章來源地址http://www.zghlxwxcb.cn/news/detail-813033.html
到了這里,關(guān)于golang中context詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!