最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語(yǔ)言使用context控制協(xié)程取消的方法步驟

 更新時(shí)間:2025年08月14日 10:23:43   作者:程序員愛(ài)釣魚(yú)  
本文將通過(guò)一個(gè)實(shí)際案例,使用?context?控制協(xié)程的取消,避免資源泄露,實(shí)現(xiàn)優(yōu)雅退出,具有一定的參考價(jià)值,感興趣的可以了解一下

在并發(fā)編程中,合理地控制協(xié)程(goroutine)的生命周期是保證程序穩(wěn)定性和資源可控使用的關(guān)鍵。Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的 context 包正是為了解決這一問(wèn)題而生。它為我們提供了取消信號(hào)、超時(shí)控制、請(qǐng)求作用域的值傳遞等功能。

本文將通過(guò)一個(gè)實(shí)際案例,演示如何使用 context 控制協(xié)程的取消,避免資源泄露,實(shí)現(xiàn)優(yōu)雅退出。

一、什么是context

context 是 Go 1.7 起加入標(biāo)準(zhǔn)庫(kù)的一個(gè)重要包,用于跨 API 邊界傳遞取消信號(hào)、超時(shí)時(shí)間、截止時(shí)間等信息。

主要接口定義如下:

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key any) any
}

其中最關(guān)鍵的是:

  • • Done():返回一個(gè) channel,當(dāng) context 被取消或超時(shí)關(guān)閉時(shí),該 channel 會(huì)被關(guān)閉;
  • • Err():返回取消的原因,例如 context.Canceled 或 context.DeadlineExceeded

二、常見(jiàn)創(chuàng)建方式

Go 提供了以下常用方式創(chuàng)建 context:

ctx := context.Background() // 最頂層、永不取消的 context
ctx, cancel := context.WithCancel(parent) // 手動(dòng)調(diào)用 cancel() 取消
ctx, cancel := context.WithTimeout(parent, 3*time.Second) // 指定超時(shí)時(shí)間
ctx, cancel := context.WithDeadline(parent, time.Now().Add(3*time.Second)) // 到期時(shí)間點(diǎn)

這些 context 都可以傳遞到協(xié)程中,通過(guò) ctx.Done() 控制協(xié)程的停止。

三、實(shí)戰(zhàn)案例:使用context控制任務(wù)協(xié)程

場(chǎng)景描述

假設(shè)我們要運(yùn)行一個(gè)任務(wù),該任務(wù)每秒輸出一次“正在處理”,但當(dāng)主程序在某個(gè)時(shí)機(jī)需要終止它(比如點(diǎn)擊“停止按鈕”或超時(shí)),我們要優(yōu)雅地通知協(xié)程退出。

示例代碼

package main

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

func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("worker 任務(wù)被取消:", ctx.Err())
            return
        default:
            fmt.Println("worker 正在處理任務(wù)...")
            time.Sleep(1 * time.Second)
        }
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())

    go worker(ctx)

    // 主線程運(yùn)行5秒后取消任務(wù)
    time.Sleep(5 * time.Second)
    cancel()

    // 等待協(xié)程打印結(jié)束語(yǔ)
    time.Sleep(1 * time.Second)
    fmt.Println("主程序退出")
}

輸出結(jié)果

worker 正在處理任務(wù)...
worker 正在處理任務(wù)...
worker 正在處理任務(wù)...
worker 正在處理任務(wù)...
worker 正在處理任務(wù)...
worker 任務(wù)被取消: context canceled
主程序退出

可以看到,主程序通過(guò) cancel() 取消了 context,協(xié)程立即響應(yīng)退出了。

四、使用context.WithTimeout實(shí)現(xiàn)超時(shí)控制

除了手動(dòng)調(diào)用 cancel,我們還可以通過(guò)設(shè)定超時(shí)時(shí)間自動(dòng)取消任務(wù)。

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()

    go worker(ctx)

    time.Sleep(5 * time.Second) // 主線程等待更久,看任務(wù)是否能自動(dòng)終止
    fmt.Println("主程序退出")
}

運(yùn)行結(jié)果類似:

worker 正在處理任務(wù)...
worker 正在處理任務(wù)...
worker 正在處理任務(wù)...
worker 任務(wù)被取消: context deadline exceeded
主程序退出

這表示:即使主程序沒(méi)有主動(dòng)調(diào)用 cancel(),協(xié)程也在 3 秒后收到 context 超時(shí)通知并正常退出。

五、多個(gè)協(xié)程共享一個(gè)context

我們可以啟動(dòng)多個(gè)協(xié)程,并使用同一個(gè) context 控制它們:

func main() {
    ctx, cancel := context.WithCancel(context.Background())

    for i := 1; i <= 3; i++ {
        go func(id int) {
            for {
                select {
                case <-ctx.Done():
                    fmt.Printf("協(xié)程 %d 接收到取消信號(hào)\n", id)
                    return
                default:
                    fmt.Printf("協(xié)程 %d 正在工作\n", id)
                    time.Sleep(1 * time.Second)
                }
            }
        }(i)
    }

    time.Sleep(4 * time.Second)
    cancel()

    time.Sleep(1 * time.Second)
    fmt.Println("主程序退出")
}

輸出:

協(xié)程 1 正在工作
協(xié)程 2 正在工作
協(xié)程 3 正在工作
...(多次輸出)
協(xié)程 1 接收到取消信號(hào)
協(xié)程 2 接收到取消信號(hào)
協(xié)程 3 接收到取消信號(hào)
主程序退出

這樣我們實(shí)現(xiàn)了“一鍵終止所有協(xié)程”。

六、最佳實(shí)踐建議

  • • 永遠(yuǎn)使用 context.WithCancel / WithTimeout 返回的 cancel() 函數(shù),不要忘記 defer cancel()
  • • 在需要可控中止的任務(wù)(如網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)操作、循環(huán)處理)中傳入 context;
  • • 對(duì) ctx.Done() 的監(jiān)聽(tīng)要放在協(xié)程內(nèi)部適當(dāng)位置,防止資源泄露;
  • • 在請(qǐng)求鏈中傳遞 context,以實(shí)現(xiàn)鏈路級(jí)別的取消與超時(shí)控制。

七、結(jié)語(yǔ)

context 是 Go 并發(fā)控制中不可或缺的利器。它不僅解決了協(xié)程取消的痛點(diǎn),還能為任務(wù)設(shè)置統(tǒng)一的生命周期控制邏輯,是構(gòu)建高可靠網(wǎng)絡(luò)服務(wù)、后臺(tái)任務(wù)系統(tǒng)、爬蟲(chóng)等并發(fā)程序的基礎(chǔ)設(shè)施。

如果你還沒(méi)有在項(xiàng)目中大量使用它,不妨從今天開(kāi)始重構(gòu)代碼,使用 context 管理協(xié)程生命周期,讓你的 Go 程序更穩(wěn)定、更可控!

到此這篇關(guān)于Go語(yǔ)言使用context控制協(xié)程取消的方法步驟的文章就介紹到這了,更多相關(guān)Go context控制協(xié)程取消內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言中動(dòng)態(tài)調(diào)用不同簽名的函數(shù)的實(shí)現(xiàn)

    Go語(yǔ)言中動(dòng)態(tài)調(diào)用不同簽名的函數(shù)的實(shí)現(xiàn)

    本文主要介紹了Go語(yǔ)言中動(dòng)態(tài)調(diào)用不同簽名的函數(shù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-05-05
  • Golang使用http協(xié)議實(shí)現(xiàn)心跳檢測(cè)程序過(guò)程詳解

    Golang使用http協(xié)議實(shí)現(xiàn)心跳檢測(cè)程序過(guò)程詳解

    這篇文章主要介紹了Golang使用http協(xié)議實(shí)現(xiàn)心跳檢測(cè)程序過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-03-03
  • 淺談go語(yǔ)言renderer包代碼分析

    淺談go語(yǔ)言renderer包代碼分析

    本篇文章主要介紹了淺談go語(yǔ)言renderer包代碼分析,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • Golang中禁止拷貝的實(shí)現(xiàn)代碼

    Golang中禁止拷貝的實(shí)現(xiàn)代碼

    這篇文章主要給大家介紹了關(guān)于Golang中實(shí)現(xiàn)禁止拷貝的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • Go語(yǔ)言并發(fā)之Sync包的6個(gè)關(guān)鍵概念總結(jié)

    Go語(yǔ)言并發(fā)之Sync包的6個(gè)關(guān)鍵概念總結(jié)

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言并發(fā)中Sync包的6個(gè)關(guān)鍵概念,文中的示例代碼講解詳細(xì),對(duì)我們深入學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下
    2023-05-05
  • golang log4go的日志輸出優(yōu)化詳解

    golang log4go的日志輸出優(yōu)化詳解

    log4go源于google的一項(xiàng)log工程,但官方已經(jīng)停止維護(hù)更新,下面這篇文章主要給大家介紹了關(guān)于golang log4go的日志輸出優(yōu)化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-12-12
  • golang 通用Contains方法分享

    golang 通用Contains方法分享

    這篇文章主要介紹了golang 通用Contains方法分享,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • Go整合captcha實(shí)現(xiàn)驗(yàn)證碼功能

    Go整合captcha實(shí)現(xiàn)驗(yàn)證碼功能

    最近在使用Go語(yǔ)言搞一個(gè)用戶登錄&注冊(cè)的功能,我們油然會(huì)產(chǎn)生一種增加驗(yàn)證碼的想法。后來(lái)在GitHub上找到了這個(gè)名叫captcha的插件,于是就利用文檔進(jìn)行了初步的學(xué)習(xí),并融入到自己的項(xiàng)目中,整個(gè)過(guò)程下來(lái)感覺(jué)這個(gè)插件的設(shè)計(jì)非常巧妙
    2023-03-03
  • golang 如何刪除二進(jìn)制文件中的源碼路徑信息

    golang 如何刪除二進(jìn)制文件中的源碼路徑信息

    這篇文章主要介紹了golang 如何刪除二進(jìn)制文件中的源碼路徑信息,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • go語(yǔ)言中反射機(jī)制的三種使用場(chǎng)景

    go語(yǔ)言中反射機(jī)制的三種使用場(chǎng)景

    本文主要介紹了go語(yǔ)言中反射機(jī)制的三種使用場(chǎng)景,包括JSON解析、ORM框架和接口適配,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-02-02

最新評(píng)論

习水县| 陕西省| 岑巩县| 杭锦旗| 三河市| 连州市| 富锦市| 大安市| 芜湖县| 阜城县| 女性| 徐州市| 梅河口市| 梁平县| 武冈市| 石狮市| 阿瓦提县| 静海县| 陕西省| 屯昌县| 中山市| 龙井市| 沧州市| 汉源县| 霍林郭勒市| 苏尼特左旗| 阿巴嘎旗| 宣武区| 涡阳县| 昌江| 通城县| 汾阳市| 布拖县| 含山县| 广元市| 张家川| 桐城市| 增城市| 石嘴山市| 温州市| 钦州市|