本文共 1698 字,大约阅读时间需要 5 分钟。
context主要是用于多个协程之间的统一控制,主要包括统一取消和统一超时。下面是关于context对多个协程进行统一控制的示例:
假设有这样一个应用场景,一个公司(main)有一名经理(manager)和两名工人(worker),公司下班(main exit)有两种可能:一:工人(worker)的工作时间已经达到合同约定的最大时长;二:经理(manager)提前叫停收工。两种可能满足其中一个即可下班。
示例:
package mainimport ( "context" "fmt" "time")//worker工作的最大时长,超过这个时长worker自行收工无需等待manager叫停const MAX_WORKING_DURATION = 5 * time.Second//达到实际工作时长后,manager可以提前叫停const ACTUAL_WORKING_DURATION = 10 * time.Secondfunc main() { ctxWithCancel, cancel := context.WithTimeout(context.Background(), MAX_WORKING_DURATION) go worker(ctxWithCancel, "[1]") go worker(ctxWithCancel, "[2]") go manager(cancel) <-ctxWithCancel.Done() //暂停1秒便于协程的打印输出 time.Sleep(1 * time.Second) fmt.Println("company closed")}func manager(cancel func()){ time.Sleep(ACTUAL_WORKING_DURATION) fmt.Println("manager called cancel()") cancel()}func worker(ctxWithCancel context.Context, name string) { for { select { case <-ctxWithCancel.Done(): fmt.Println(name, "return for ctxWithCancel.Done()") return default: fmt.Println(name, "working") } time.Sleep(1 * time.Second) }}
输出:
[1] working[2] working[2] working[1] working[1] working[2] working[2] working[1] working[1] working[2] working[1] return for ctxWithCancel.Done()[2] return for ctxWithCancel.Done()company closed
可见,这次下班是因为ctxWithCancel的计时器到点引起的。
把实际工作时长改成2秒,最大工作时长不变,再运行一次
//worker工作的最大时长,超过这个时长worker自行收工无需等待manager叫停const MAX_WORKING_DURATION = 5 * time.Second//达到实际工作时长后,manager可以提前叫停const ACTUAL_WORKING_DURATION = 2 * time.Second
输出:
[1] working[2] working[2] working[1] workingmanager called cancel()[1] return for ctxWithCancel.Done()[2] return for ctxWithCancel.Done()company closed
可见,worker只工作了2秒就被manager提前叫停了。
至于为什么要用context而不是用计时器加通道来实现,请见另一篇文章
转载地址:http://xnmwn.baihongyu.com/