go---goroutine
阿新 • • 發佈:2019-01-08
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