在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Context通常被译作上下文,它是一个比较抽象的概念。在讨论链式调用技术时也经常会提到上下文。一般理解为程序单元的一个运行状态、现场、快照,而翻译中上下又很好地诠释了其本质,上下则是存在上下层的传递,上会把内容传递给下。在Go语言中,程序单元也就指的是Goroutine。 在Go语言中控制并发有两种经典的方式,一种是WaitGroup,另外一种就是Context。 Context业务场景每个Goroutine在执行之前,都要先知道程序当前的执行状态,通常将这些执行状态封装在一个Context变量中,传递给要执行的Goroutine中。上下文则几乎已经成为传递与请求同生存周期变量的标准方法。在网络编程下,当接收到一个网络请求Request,在处理这个Request的goroutine中,可能需要在当前gorutine继续开启多个新的Goroutine来获取数据与逻辑处理(例如访问数据库、RPC服务等),即一个请求Request,会需要多个Goroutine中处理。而这些Goroutine可能需要共享Request的一些信息;同时当Request被取消或者超时的时候,所有从这个Request创建的所有Goroutine也应该被结束。 初识Context上面说的这种场景是存在的,比如一个网络请求Request,每个Request都需要开启一个goroutine做一些事情,这些goroutine又可能会开启其他的goroutine。所以我们需要一种可以跟踪goroutine的方案,才可以达到控制他们的目的,这就是Go语言为我们提供的Context,称之为上下文非常贴切,它就是goroutine的上下文。 func main() { 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 with用法context.WithValue() 设置值传递 context.WithCancel() 设置关闭Groutine context.WithTimeout() 设置超时时间 context.WithDeadine() 设置绝对过期时间
context.TODO() 返回一个非nil的空Context,当不清楚使用哪种Context或尚不可用时,应该使用context.TODO context.Backgroup() 返回一个非nil的空Context,也是一个根Context(top-level Context) // Background returns a non-nil, empty Context. It is never canceled, has no Context控制多个goroutine使用Context控制一个goroutine的例子如上,非常简单,下面我们看看控制多个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) } } } 示例中启动了3个监控goroutine进行不断的监控,每一个都使用了Context进行跟踪,当我们使用 Context传递消息package main import ( "context" "fmt" "time" "sync" ) func worker(ctx context.Context, wg sync.WaitGroup) { traceCode, ok := ctx.Value("TRACE_CODE").(string) if ok { fmt.Printf("trace_code:%s\n", traceCode) } for { fmt.Printf("worker, trace_code:%s\n", traceCode) select { case <- ctx.Done(): return default: time.Sleep(time.Second) } } wg.Done() } func main() { ctx, cancel := context.WithCancel(context.Background()) ctx = context.WithValue(ctx, "TRACE_CODE", "12345678") var waitGroup sync.WaitGroup go worker(ctx, waitGroup) time.Sleep(3 * time.Second) cancel() waitGroup.Wait() }
转载至: http://www.flysnow.org/2017/05/12/go-in-action-go-context.html https://studygolang.com/articles/13343
|
请发表评论