在goroutine中,使用select调用<-ctx.Done()判断是否要结束,如果接受到值的话,就可以返回结束goroutine了;如果接收不到,就会继续进行监控。
那么是如何发送结束指令的呢?这就是示例中的cancel函数啦,它是我们调用context.WithCancel(parent)函数生成子Context的时候返回的,第二个返回值就是这个取消函数,它是CancelFunc类型的。我们调用它就可以发出取消指令,然后我们的监控goroutine就会收到信号,就会返回结束。
Context控制多个goroutine
func testMultiContext() {
ctx, cancel := context.WithCancel(context.Background())
go watch(ctx, "watch1")
go watch(ctx, "watch2")
time.Sleep(10 * time.Second)
fmt.Println("cancel all goroutine")
cancel()
//为了检测监控过是否停止,如果没有监控输出,就表示停止了
time.Sleep(5 * time.Second)
}
func watch(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Println(name," is done")
return
default:
fmt.Println(name," is running")
time.Sleep(2 * time.Second)
}
}
}
Context接口
// A Context carries a deadline, cancelation signal, and request-scoped values
// across API boundaries. Its methods are safe for simultaneous use by multiple
// goroutines.
type Context interface {
// Done returns a channel that is closed when this Context is canceled
// or times out.
Done() <-chan struct{}
// Err indicates why this context was canceled, after the Done channel
// is closed.
Err() error
// Deadline returns the time when this Context will be canceled, if any.
Deadline() (deadline time.Time, ok bool)
// Value returns the value associated with key or nil if none.
Value(key interface{}) interface{}
}
Context 使用原则
- 不要把Context放在结构体中,要以参数的方式传递
- 以Context作为参数的函数方法,应该把Context作为第一个参数,放在第一位。
- 给一个函数方法传递Context的时候,不要传递nil,如果不知道传递什么,就使用context.TODO
- Context的Value相关方法应该传递必须的数据,不要什么数据都使用这个传递
- Context是线程安全的,可以放心的在多个goroutine中传递
参考文献
- https://blog.golang.org/context
本文来自:简书
感谢作者:cp3_1dbc
查看原文:go中控制并发的两种方式
相关阅读 >>
关于处理电商系统订单状态的流转,分享下我的技术方案(附带源码)
[系列] Go - 学习 grpc.dial(target string, opts …dialoption) 的写法
Golang 获取三种不同的路径方法(执行路径,项目路径,文件路径)
更多相关阅读请进入《Go》频道 >>
Go语言101
一个与时俱进的Go编程知识库。