Go   发布时间:2022-04-09  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了GOLANG的context和并发模型大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

GOLANG1.7新增了context,最初这个package是在golang.org/x/net/context中的,后来证实对很多程序都是必须的,就纳入了标准库。

对context的介绍是在context,读这个blog之前,要先读pipelines(pipelines提出了使用close(chan)的方式广播退出事件)。

一般来说,context是用在request的处理,例如http请求的处理中,可能会开启多个goroutIne,比如:

@H_502_11@http.HandleFunc(func(w http.ResponseWriter,r *http.request){ wg := sync.WaitGroup{} wg.Add(2) var result0 String go func(){ defer wg.Done() res0,err := http.Get("http://server0/api0") // Parse res0 to result0. }() var result1 String go func(){ defer wg.Done() res1,err := http.Get("http://server1/api1") // Parse res1 to result1. }() wg.Wait() w.Write([]byte(result0 + result1) })

实际上这个程序是不能这么写的,如果这两个goroutIne请求的时间比较长,让用户一直等着么?如果用户取消了请求,关闭了连接呢?如果用户指定了超时时间呢?

另外,虑如何关闭一个http服务器,比如需要关闭listener后重新侦听一个新的端口:

@H_502_11@var server *http.Server go func() { server = &http.Server{Addr: addr,Handler: nil} if err = server.ListenAndServe(); err != nil { ol.E(nil,"API serve Failed,err is",err) return } }()

我们如何确保goroutIne已经退出后,然后才返回重新开启服务器?如果只是server.Close(或者GO1.8之前用listener.Close),如何接收外部的事件?如果是goroutIne自己的问题,例如端口占用了,如何通知程序退出?直接用os.Exit明显是太粗鲁的做法。

context中,有一段话非常关键:

@H_502_11@A Context does not have a Cancel method for the same reason the Done chAnnel is receive-only: the function receiving a cancelation signal is usually not the one that sends the signal. In particular,when a parent operation starts goroutInes for sub- operations,those sub-operations should not be able to cancel the parent. Instead,the WithCancel function (described below) provides a way to cancel a new Context value.

也就是说,context没有提供Cancel方法,因为parent goroutIne会调用Cancel,在所有sub goroutInes中只需要读context.Done()就可以,也就是只是接收退出信号。

还有一处地方,说明了Context应该放在参数中:

@H_502_11@Server frameworks that want to build on Context should provide implementations of Context to bridge between their packages and those that expect a Context parameter. their client libraries would then accept a Context from the calling code. By establishing a common interface for request-scoped data and cancelation,Context makes it easier for package developers to share code for creaTing scalable services.

只读取chan的好处是,可以使用close(chan)方式通知所有goroutIne退出

使用COntext和WaitGroup,同步和取消服务器的例子:

@H_502_11@func httpAPIServe(ctx context.Context) { http.HandleFunc("/api",func(w http.ResponseWriter,r *http.request) { }) ctx,cancel := context.WithCancel(ctX) wg := &sync.WaitGroup{} defer wg.Wait() wg.Add(1) var server *http.Server go func(ctx context.Context) { defer wg.Done() defer cancel() server = &http.Server{Addr: addr,Handler: nil} _ = server.ListenAndServe() }(ctX) SELEct { case <-ctx.Done(): server.Close() } } wg := sync.WaitGroup{} defer wg.Wait() ctx,cancel := context.WithCancel(context.BACkground()) wg.Add(1) go func(ctx context.Context) { defer wg.Done() defer cancel() httpAPIServe(ctX) }(ctX) wg.Add(1) go func(ctx context.Context) { defer wg.Done() defer cancel() // Other server,such as: // UDPServer(ctX) }(ctX)

这个程序实际上包含了几条通道:

  1. 如果需要主动退出通知所有listener做清理然后退出,可以在parent goroutIne调用cancel。上面是在任意goroutIne退出后,通知所有goroutIne退出。@H_489_257@
  2. 如果某个sub-goroutIne需要通知其他sub-goroutIne退出,不应该直接调用cancel方法,而是通过chan(上面是quit)在goroutIne返回时告知parent goroutIne,由parent goroutIne处理。@H_489_257@
  3. 在sub-goroutIne中,如果还需要启动goroutIne,可以新开context做同步。如果是可以直接用SELEct,那就可以不用新开goroutIne,而是直接SELEct ctx,等待退出。一般而言,goroutIne的退出,就意味着一个退出的事件,而这个事件应该由parent goroutIne处理,而不能直接广播给其他goroutIne。@H_489_257@
  4. chan的读写,参读取 chan写入chan。@H_489_257@

特别是对于library,在参数中支持context,是非常重要的一个要素,这样可以收取到user要求退出或cancel的信号。

大佬总结

以上是大佬教程为你收集整理的GOLANG的context和并发模型全部内容,希望文章能够帮你解决GOLANG的context和并发模型所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。