go---goroutine

stop := make(chan bool)

	go func() {
		for {
			select {
			case <-stop:
				fmt.Println("监控退出,停止了...")
				return
			default:
				fmt.Println("goroutine监控中...")
				time.Sleep(2 * time.Second)
			}
		}
	}()

	time.Sleep(10 * time.Second)
	fmt.Println("可以了,通知监控停止")
	stop<- true
	//为了检测监控过是否停止,如果没有监控输出,就表示停止了
	time.Sleep(5 * time.Second)

以上是使用chan + select 来结束goroutine。但是有弊端:当有多个goroutine需要控制结束就很复杂。

定义一个stop的chan,通知他结束后台goroutine。在后台goroutine中,判断stop是否可以接收到值,如果可以接收到,就表示可以停止退出了,如果没有接收到,就会执行default里面的监控逻辑,极限监控,直到收到stop的通知。

下面使用go的context来实现:

ctx, cancel := context.WithCancel(context.Background())
	go func(ctx context.Context) {
		for {
			select {
			case <-ctx.Done():
				fmt.Println("监控退出,停止了...")
				return
			default:
				fmt.Println("goroutine监控中...")
				time.Sleep(2 * time.Second)
			}
		}
	}(ctx)

	time.Sleep(10 * time.Second)
	fmt.Println("可以了,通知监控停止")
	cancel()
	//为了检测监控过是否停止,如果没有监控输出,就表示停止了
	time.Sleep(5 * time.Second)

 context.Backgroud()返回一个空的Context,这个空的Cobtext一般用于整个Context树的根节点。

使用context.WithCancel(parent)函数,创建一个可取消的子context,当作参数传递给goroutine,这样就可以使用这个子context跟踪这个goroutine。

context控制多个goroutine

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	go watch(ctx,"【监控1】")
	go watch(ctx,"【监控2】")
	go watch(ctx,"【监控3】")

	time.Sleep(10 * time.Second)
	fmt.Println("可以了,通知监控停止")
	cancel()
	//为了检测监控过是否停止,如果没有监控输出,就表示停止了
	time.Sleep(5 * time.Second)
}

func watch(ctx context.Context, name string) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println(name,"监控退出,停止了...")
			return
		default:
			fmt.Println(name,"goroutine监控中...")
			time.Sleep(2 * time.Second)
		}
	}
}

转自:https://www.flysnow.org/2017/05/12/go-in-action-go-context.html

猜你喜欢

转载自blog.csdn.net/u010918487/article/details/85702679