golang中上下文有哪些应用场景

  介绍

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中上下文有哪些应用场景