go 主协程等待子协程执行完毕再执行方法

Posted dqz_nihao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 主协程等待子协程执行完毕再执行方法的主要内容,如果未能解决你的问题,请参考以下文章

go 主协程等待子协程执行完毕再执行方法

go语音之进阶篇主协程先退出导致子协程没来得及调用

Go Web爬虫并发实现

[GO]定时器的停止

golang/go语言sync同步包中的WaitGroup等待组Mutex互斥锁和RWMutex读写锁

golang/go语言sync同步包中的WaitGroup等待组Mutex互斥锁和RWMutex读写锁