go 等待所有 goroutine 执行结束的方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go 等待所有 goroutine 执行结束的方法相关的知识,希望对你有一定的参考价值。
参考技术A 通常我们在 main 中需要等待所有的 goroutine 都执行完毕时再退出一般有两种方法
方法一大家都能想到用 channel 进行同步
方法二用 sync.WaitGroup,这也是官方推荐方法,不需要知道 gotoutine 的个数
go 主协程等待子协程执行完毕再执行方法
go 主协程通知子协程退出方法-go面试
方式一:用全局变量
主goroutine使用全局变量通知子goroutine退出
func f()
defer wg.Done()
for
fmt.Println("中国")
time.Sleep(time.Millisecond * 500)
if notify
break
func main()
wg.Add(1)
go f()
time.Sleep(time.Second * 5)
notify = true
wg.Wait()
方式二:用channel+select
通过子goroutine接收channel的值让goroutine退出
var wg sync.WaitGroup
var exitChan = make(chan bool, 1)
func f()
defer wg.Done()
LOOP:
for
fmt.Println("中国")
time.Sleep(time.Millisecond * 500)
select
case <-exitChan:
break LOOP
default:
func main()
wg.Add(1)
go f()
time.Sleep(time.Second * 5)
exitChan <- true
wg.Wait()
但是在某些场景下,例如处理一个请求衍生了很多协程,这些协程之间是相互关联的:需要共享一些全局变量、有共同的 deadline 等,而且可以同时被关闭。再用 channel+select 就会比较麻烦,这时就可以通过 context 来实现。
在这里停止worker1的情况下可以使用channel+select,而停止worker2,3的情况下,channel+select就显得不是非常友好,使用context就可以。
一句话:context 用来解决 goroutine 之间退出通知、元数据传递的功能。
方式三:用context
context方法本质上也是channel,只不过进一步包装,更具有实用性
var wg sync.WaitGroup
func f2(ctx context.Context)
defer wg.Done()
LOOP:
for
fmt.Println("上海")
time.Sleep(time.Millisecond * 500)
select
case <-ctx.Done():
break LOOP
default:
func f(ctx context.Context)
defer wg.Done()
f2(ctx)
LOOP:
for
fmt.Println("中国")
time.Sleep(time.Millisecond * 500)
select
case <-ctx.Done():
break LOOP
default:
func main()
ctx, cancel := context.WithCancel(context.Background())
defer cancel() //通知子goroutine结束
wg.Add(1)
go f(ctx)
time.Sleep(time.Second * 5)
wg.Wait()
go 主协程等待子协程执行完毕再执行方法
方法一:sync.WaitGroup
方法二:contextContext
以上是关于go 等待所有 goroutine 执行结束的方法的主要内容,如果未能解决你的问题,请参考以下文章