1. 程式人生 > >go---goroutine

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