package main

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

func f2(ctx context.Context) {
	n := 1
	for {
		time.Sleep(2 * time.Second)
		select {
		case <-ctx.Done():
			fmt.Printf("%s 结束运行\n", "f2")
			return
		default:
			fmt.Println("f2---------------->", n)
			n++
		}
	}

}

func f1(ctx context.Context) {
	go f2(ctx)
	n := 1
	for {
		time.Sleep(time.Second)
		select {
		case <-ctx.Done():
			fmt.Printf("%s 结束运行\n", ctx.Err())
			return
		default:
			fmt.Println("f1--->", n)
			n++
		}
	}

}

func main() {
	// 创建
	ctx, cancel := context.WithCancel(context.Background())
	go f1(ctx)
	time.Sleep(time.Second * 10)
	// 调用cancel方法时,会给ctx.Done这个chan就
	cancel()


	for{
		println("main....")
		time.Sleep(time.Second)
	}

}

打印结果

f1---> 1
f1---> 2
f2----------------> 1
f1---> 3
f1---> 4
f2----------------> 2
f1---> 5
f1---> 6
f2----------------> 3
f1---> 7
f1---> 8
f2----------------> 4
f1---> 9
main....
f2 结束运行
context canceled 结束运行
main....
main....
main....
main....
main....
main....
main....
main....
main....
main....
main....
main....
main....
main....
main....
main....

结论:通过上面的打印记录可以知道,在主程中调用cancel方法后,它与之相关联的f1f2 两个函数中ctx.Done() 这个分支的case 都触发了, 这说context底层在我们调用cancel方法时,往ctx.Done这个管道中写了数据。 本例也正是用此特性完成了goroutine的退出。

posted on 2020-09-10 23:37  显示账号  阅读(280)  评论(0编辑  收藏  举报