当前位置:网站首页>Basic use of Go Context

Basic use of Go Context

2022-08-10 14:53:00 EthanLeo

Go Context的基本使用

This article is mainly used to introducegolang里面context的使用,Because it was not clear beforecontext的用法,以及context的一些基本特性.

Context的使用场景

ContextThe function can be reflected from two aspects:

  1. Send a termination signal to the method
  2. Pass some common data to multiple methods

Why do you need to cancel the operation(终止信号)

简单来说,We need some termination signals,to tell our program to stop doing some unnecessary work.

用一个简单的例子来说明:

Send the request from the client to the program processing and then to the database,The normal process is shown in the figure below

But when the client sends a request,If the link is broken,Then under normal circumstances, the subsequent database query operation should be stopped,If there is no abort signal then the program will continue to execute,But the normal situation is to terminate the continued operation

So we know why the termination signal is needed

Go中ContextTerminate signaling mode

在goThere are two aspects to implementing the termination signal

  1. Listen for termination events
  2. Post a termination event

Listen for termination events

Context提供了一个Done()的方法,该方法会返回一个channel,Every time the context sends a cancel event,Both send an empty onestruct{}into this pipeline,So in order to listen to the cancellation event,我们需要等待 <-ctx.Done()The semaphore passed.

func TestListeningCancel(t *testing.T) {
 // 测试方法
 // 浏览器打开localhost:8000
 // It will return after two secondsrequest processed
 // If you disconnect immediately after sending the request then ctx.Done() 能够收到信号 执行中断
 http.ListenAndServe(":8000", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  ctx := r.Context()
  fmt.Fprint(os.Stdout, "processing request\n")

  select {
  case <-time.After(2 * time.Second):
   // 2If a signal is received in seconds
   // Indicates that the request was executed
   w.Write([]byte("request processed"))
  case <-ctx.Done():
   // 如果请求被取消 The output request was canceled
   fmt.Fprint(os.Stderr, "request cancelled")
  }
 }))
}

Send a termination event

If you have an operation to be cancelled,Then you need to send a cancel event through the context

我们可以通过ContextBuilt-in methods in the packageWithCancel(),该方法会返回一个context和一个function

ctx,fn :=context.WithCancel()

// This method assumes that an operation fails
func Operation1(ctx context.Context)error{
 time.Sleep(100 *time.Millisecond)
 return errors.New("failed")
}


func Operation2(ctx context.Context){
 select {
 case <-time.After(500*time.Millisecond):
  fmt.Println("done")
 case <-ctx.Done():
  fmt.Println("halted operation2")

 }
}

func TestEmittingCancel(t *testing.T){
 // 创建一个新的context
 ctx := context.Background()
 // Created by a primitivectx Wrap it up as a new one,with a cancel methodctx
 ctx, cancel := context.WithCancel(ctx)
 // Perform the above two operations ,Let an operation be in onego routine中
 go func() {
  err := Operation1(ctx)
  if err!=nil{
   cancel()
  }
 }()

 // 执行2The same is used when operatingctx
 Operation2(ctx)
}

This example is a demonstration,goWhen a coroutine sends a cancel signal,监听相同contextThe thread can also receive the signal,并执行操作

超时取消

contextThe package also provides a timeout cancellation methodcontext.WithTimeout,This method will automatically send a cancel signal after the countdown is over

func TestCancelWithTimeout(t *testing.T){
 // 创建一个空ctx
 ctx := context.Background()
 // 设置超时时间
 cxt, _ := context.WithTimeout(ctx, 1*time.Millisecond)

 // 创建一个请求 访问谷歌
 req, _ := http.NewRequest(http.MethodGet, "http://baidu.com"nil)
 // will have a cancel methodctxassociated with the request
 req = req.WithContext(cxt)

 client := &http.Client{}
 res, err := client.Do(req)
 if err!=nil{
  fmt.Println("Request failed:", err)
  return
 }
 fmt.Println("Response received, status code:", res.StatusCode)

}

Context Values

When there are multiple operations that need to use the same onevalue的时候,context也提供了对应的方法,Multiple execution methods can get the value,Passing by value using such a method guarantees the operation of changing the value是线程安全的

const keyID = "id"

func TestContextWithValue(t *testing.T) {
 rand.Seed(time.Now().Unix())
 ctx := context.WithValue(context.Background(), keyID, rand.Int())
 operation1(ctx)
}

func operation1(ctx context.Context) {
 log.Println("operation1 for id:", ctx.Value(keyID), " completed")
 operation2(ctx)
}

func operation2(ctx context.Context) {
 log.Println("operation2 for id:", ctx.Value(keyID), " completed")

}

以上就是context的一些基本操作,The follow-up sequence also needs to go into in-depth research

原网站

版权声明
本文为[EthanLeo]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/222/202208101431162612.html