go 优雅的结束goroutine

对于通知一个goroutine结束它的工作,遵循goroutine之间通过管道传递消息的设计理念,我们可以使用channel传递一个信号,当goroutine检测到信号,结束工作即可:

var wg sync.WaitGroup

func work(exit <-chan struct{}) {
	LABEL:
	for {
		select {
		case <-exit:
			break LABEL
		default:
			fmt.Println("working...")
			time.Sleep(time.Second * 1)
		}
	}
	wg.Done()
}

func main() {
	exit := make(chan struct{})

	wg.Add(1)
	go work(exit)

	time.Sleep(time.Second * 5)
	exit <- struct{}{}

	wg.Wait()
}

其实go语言本身的context包已经实现了这样的机制,用来处理goroutine之间切换上下文,在多个goroutine之间传递消息,也可以实现优雅关闭的效果:

func work2(ctx context.Context, cancel context.CancelFunc) {
LABEL:
	for {
		select {
		case <-ctx.Done():
			break LABEL
		default:
			fmt.Println("working...")
			time.Sleep(time.Second * 1)
		}
	}
	wg.Done()
}

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

	wg.Add(1)
	go work2(ctx, cancel)

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

	wg.Wait()
}

除了withCancel,还有withTimeout、withDeadline、withValue方式来创建context,具体使用比较简单不再介绍

posted @ 2021-11-26 21:43  moon_orange  阅读(138)  评论(0编辑  收藏  举报