Golang Go语言中 context 简介(3)-广播通知多个业务 Go 程退出

Golang Go语言中 context 简介(3)-广播通知多个业务 Go 程退出

上回聊到,context 是有父子间影响的,父 context cancel 之后,子 context 也会随之 cancel。 这次聊下广播通知多个业务 go 程退出

如何通知多个业务 go 程退出

问题描述

如果在一个业务中会起多个 go 程做一些事,每个 go 程里面会跑流式业务(流式业务可以理解为 dong dong dong 有很多步骤)。你会如何做?

  1. 基于 bool flag 吗?那你要把所有的 select chan 的地方修改成轮训,改动太大,select 多路复用的优点全没了,引入 cpu 空转。关键有时候还不能这么修改

  2. 每次退出的时候发个事件到一个专门的 message chan? 基于计算的方式,万一少发了一个,就会造成 go 程泄漏。而且 message chan 的大小也是一个头疼的地方。

  3. sync.WaitGroup? WaitGroup 只是 go 程同步等待的函数,不是事件通知用的

基于事件通知的做法

在聊之前,大家估计都知道了两个事情,如果一个 chan 被 close 掉,是可以读取多次的,close 掉一个 close 掉的 chan 是会 panic 的。ok,基于这两点认知,我们设计通知多个业务 go 程的退出代码。

```go
func testQuit(failId int, max int) {
lock := sync.Mutex{}
wg := sync.WaitGroup{}
closeOk := false
done := make(chan struct{})

wg.Add(max)
defer wg.Wait()

for i := 0; i < max; i++ {

    go func(id int) {
        defer wg.Done()

        if id == failId || id == failId-1 {
            lock.Lock()

            if !closeOk {
                close(done)
                closeOk = true
            }

            lock.Unlock()
        }   

        select {
        case <-done:
            fmt.Printf("id = %d, quit\n", id) 
        }

    }(i)
}   

}

我们利用一个 chan 被 close 是可以读取多次的特性,用作广播通知。为了避免一个 chan 会 close 两次会 panic 加入一个 flag 变量。为了 go 程安全,引入 sync.Mutex。

用 context 改造广播通知代码

context 里面实现的代码也是用 close chan 的方式实现的,可能官方看大家都是用这种方式用作广播通知,最后把这种模式加入到了标准库里面

package main

import ( “context” “fmt” “sync” )

func testContext(failId int, max int) {

var wg sync.WaitGroup

ctx, cancel := context.WithCancel(context.Background())

wg.Add(max)
defer wg.Wait()

for i := 0; i < max; i++ {

    go func(id int) {
        defer wg.Done()
        if id == failId {
            cancel()
        }

        select {
        case <-ctx.Done():
            fmt.Printf("id = %d, quit\n", id)
        }

    }(i)
}

}

func main() { testContext(1, 5) testContext(0, 5) }

我的 github

https://github.com/guonaihong/gout


更多关于Golang Go语言中 context 简介(3)-广播通知多个业务 Go 程退出的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang Go语言中 context 简介(3)-广播通知多个业务 Go 程退出的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang(Go语言)中,context包是一个强大的工具,它不仅用于管理请求的截止日期、取消信号,还能用于广播通知多个业务Go程(goroutine)退出。以下是关于如何使用context进行广播通知的简要介绍:

context.Broadcast并不是context包中直接提供的一个功能,但可以通过context.WithCancelcontext.WithTimeout等函数结合通道(channel)来实现类似的效果。

  1. 创建父Context:首先,创建一个父context,通常使用context.Background()context.TODO()作为根context

  2. 派生子Context:通过context.WithCancel创建一个可以取消的子context。这个子context将被多个业务Go程共享。

  3. 监听取消信号:在每个业务Go程中,使用select语句监听子contextDone通道。当父context被取消时,Done通道会被关闭,触发Go程退出。

  4. 广播取消:在需要通知所有业务Go程退出时,调用父context的取消函数。这将关闭所有派生自该父context的子contextDone通道,从而实现广播通知的效果。

通过这种方式,你可以有效地管理多个业务Go程的生命周期,确保在需要时它们能够优雅地退出。值得注意的是,合理设计context的传递和使用策略,对于避免资源泄漏和死锁等问题至关重要。

回到顶部