使用context.WithCancel創(chuàng)建可取消的context,調(diào)用cancel函數(shù)通知子協(xié)程退出;2. 通過ctx.Done()監(jiān)聽取消信號,子協(xié)程定期檢查ctx狀態(tài)以實現(xiàn)協(xié)程取消和超時控制。
在Go語言中,context 包是處理請求生命周期、超時控制和協(xié)程取消的核心工具。它常用于Web服務(wù)、數(shù)據(jù)庫調(diào)用、API請求等需要控制執(zhí)行時間或主動中斷任務(wù)的場景。下面直接講清楚怎么用 context 實現(xiàn)超時控制和協(xié)程取消。
Context 是一個接口,包含截止時間、鍵值對和取消信號。它不能被修改,只能通過派生生成新的 context。推薦始終將 context 作為函數(shù)的第一個參數(shù),命名為 ctx。
示例:func doWork(ctx context.Context) { // 使用 ctx 控制邏輯 }
最常用的根 context 是 context.Background(),通常用于主函數(shù)或請求入口。
使用 context.WithCancel 可以創(chuàng)建一個可取消的 context。當(dāng)調(diào)用 cancel 函數(shù)時,所有派生的 context 都會被通知取消。
立即學(xué)習(xí)“go語言免費學(xué)習(xí)筆記(深入)”;
代碼示例:ctx, cancel := context.WithCancel(context.Background()) <p>go func() { defer cancel() // 任務(wù)完成時調(diào)用 cancel time.Sleep(2 * time.Second) fmt.Println("任務(wù)完成") }()</p><p>select { case <-ctx.Done(): fmt.Println("收到取消信號:", ctx.Err()) }
這里 ctx.Done() 返回一個 channel,當(dāng) cancel 被調(diào)用或超時,channel 會被關(guān)閉,可用于通知子協(xié)程退出。
子協(xié)程中應(yīng)定期檢查 ctx 是否被取消:
for { select { case <-ctx.Done(): fmt.Println("協(xié)程退出") return default: // 執(zhí)行任務(wù) } }
更常見的需求是設(shè)置超時時間,使用 context.WithTimeout 或 context.WithDeadline。
WithTimeout 示例:ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() <p>go func() { time.Sleep(4 * time.Second) cancel() // 超時前手動完成也可調(diào)用 }()</p><p><-ctx.Done() fmt.Println("超時或取消:", ctx.Err())
如果 3 秒內(nèi)未完成,ctx.Done() 會觸發(fā),ctx.Err() 返回 context.DeadlineExceeded。
這種機(jī)制非常適合控制 HTTP 請求或數(shù)據(jù)庫查詢的最長執(zhí)行時間。
結(jié)合 net/http,可以將 context 傳給請求,實現(xiàn)精確控制。
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() <p>req, _ := http.NewRequest("GET", "<a href="http://ipnx.cn/link/c19fa3728a347ac2a373dbb5c44ba1c2">http://ipnx.cn/link/c19fa3728a347ac2a373dbb5c44ba1c2</a>", nil) req = req.WithContext(ctx) // Go 1.13 后推薦使用 req = req.Clone(ctx)</p><p>client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("請求失敗:", err) return } defer resp.Body.Close() fmt.Println("狀態(tài)碼:", resp.StatusCode)
這個請求最多等待 2 秒,即使服務(wù)器要 3 秒才響應(yīng),也會被中斷。
基本上就這些。context 的關(guān)鍵是“傳遞”和“監(jiān)聽 Done”。只要在協(xié)程中持續(xù)監(jiān)聽 ctx.Done(),就能實現(xiàn)優(yōu)雅取消。超時不復(fù)雜,但容易忽略 defer cancel(),記得釋放資源。
以上就是Golang的context庫怎么用 超時控制與協(xié)程取消方案的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進(jìn)程會占用資源并降低性能。幸運的是,許多工具可以讓 Windows 保持平穩(wěn)運行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號