golang中上下文有哪些应用场景?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!
golang中上下文的使用场景
上下文在Go1.7之后就进入标准库中了。它主要的用处如果用一句话来说,是在于控制goroutine的生命周期。当一个计算任务被goroutine承接了之后,由于某种原因(超时,或者强制退出)我们希望中止这个goroutine的计算任务,那么就用得到这个上下文了。
本文主要来盘一盘golang中上下文的一些使用场景:
<>强场景一:RPC调用强>
在主goroutine上有4个RPC, RPC2/3/4是并行请求的,我们这里希望在RPC2请求失败之后,直接返回错误,并且让RPC3/4停止继续计算。这个时候,就使用的到上下文。
这个的具体实现如下面的代码。
主要包 导入( “context" “sync" “;github.com/pkg/errors" ) func Rpc (ctx上下文。背景下,错误url字符串){ 结果:=让陈(int) 犯错:=(陈错误) 去func () {//进行RPC调用,并且返回是否成功,成功通过结果传递成功信息,错误通过错误传递错误信息 isSuccess:=true 如果isSuccess { 结果& lt; - 1 其他}{ 犯错& lt; - errors.New(“一些错误happen") } }() 选择{ & lt;——ctx.Done ()://其他RPC调用调用失败 返回ctx.Err () 例e:=& lt;——错://本RPC调用失败,返回错误信息 返回e & lt;——结果://本RPC调用成功,不返回错误信息 返回nil } } 函数main () { ctx、取消:=context.WithCancel (context.Background ())//RPC1调用 错:=Rpc (ctx,“http://rpc_1_url") 如果犯错!=nil { 返回 } wg:=sync.WaitGroup {}//RPC2调用 wg.Add (1) 去func () { 推迟wg.Done () 错:=Rpc (ctx,“http://rpc_2_url") 如果犯错!=nil { 取消() } }()//RPC3调用 wg.Add (1) 去func () { 推迟wg.Done () 错:=Rpc (ctx,“http://rpc_3_url") 如果犯错!=nil { 取消() } }()//RPC4调用 wg.Add (1) 去func () { 推迟wg.Done () 错:=Rpc (ctx,“http://rpc_4_url") 如果犯错!=nil { 取消() } }() wg.Wait () }
当然我这里使用了waitGroup来保证主要函数在所有RPC调用完成之后才退出。
在RPC函数中,第一个参数是一个CancelContext,这个上下文形象的说,就是一个传话筒,在创建CancelContext的时候,返回了一个听声器(ctx)和话筒(取消函数)。所有的goroutine都拿着这个听声器(ctx),当主goroutine想要告诉所有goroutine要结束的时候,通过取消函数把结束的信息告诉给所有的goroutine。当然所有的goroutine都需要内置处理这个听声器结束信号的逻辑())(ctx→完成。我们可以看RPC函数内部,通过一个选择来判断ctx的完成和当前的RPC调用哪个先结束。
这个waitGroup和其中一个RPC调用就通知所有RPC的逻辑,其实有一个包已经帮我们做好了.errorGroup。具体这个errorGroup包的使用可以看这个包的测试例子。
有人可能会担心我们这里的cancel()会被多次调用,上下文包的取消调用是幂等的,可以放心多次调用。
我们这里不妨品一下,这里的RPC函数,实际上我们的这个例子里面是一个“阻塞式”的请求,这个请求如果是使用http.Get或者http.Post来实现,实际上RPC函数的goroutine结束了,内部的那个实际的http.Get却没有结束,所以,需要理解下,这里的函数最好是“非阻塞”的,比如是http。做的,然后可以通过某种方式进行中断。比如像这篇文章取消http。使用上下文中请求的这个例子:
func httpRequest ( ctx context.Context, 客户端* http.Client, 要求* http.Request, 陈respChan[]字节, 陈errChan错误 ) { 要求=req.WithContext (ctx) tr:=, http.Transport {} 客户端。运输=tr 去func () { 职责,犯错:=client.Do(要求) 如果犯错!=nil { errChan & lt; -犯错 } 如果resp !=nil { 推迟resp.Body.Close () respData犯错:=ioutil.ReadAll (resp.Body) 如果犯错!=nil { errChan & lt; -犯错 } respChan & lt;——respData 其他}{ errChan & lt; - errors.New (“HTTP请求failed") } }() 为{ 选择{ & lt; -ctx.Done (): tr.CancelRequest(要求) errChan & lt; - errors.New (“HTTP请求cancelled") 返回 案例& lt; -errChan: tr.CancelRequest(要求) 返回 } } }golang中上下文有哪些应用场景