wx

关注公众号领取Go学习资料

wx

洋葱小店

Go并发模式:Context


介绍

在Go服务器中,每个传入请求都在自己的goroutine中处理。请求处理程序通常启动额外的goroutine来访问后台,如数据库和RPC服务。处理请求的goroutine集合通常需要访问特定于请求的值,例如用户身份标识、授权令牌和请求的超时时间等。当一个请求被取消或请求超时时,所有处理该请求的goroutine都应该迅速退出,这样系统就可以回收它们正在使用的资源。《Go Concurrency Patterns: Context

Context

context文包的核心是Context 接口类型:

// A Context carries a deadline, cancellation signal, and request-scoped values
// across API boundaries. Its methods are safe for simultaneous use by multiple
// goroutines.
type Context interface {
    // Done returns a channel that is closed when this Context is canceled
    // or times out.
    Done() <-chan struct{}

    // Err indicates why this context was canceled, after the Done channel
    // is closed.
    Err() error

    // Deadline returns the time when this Context will be canceled, if any.
    Deadline() (deadline time.Time, ok bool)

    // Value returns the value associated with key or nil if none.
    Value(key interface{}) interface{}
}
  • Done 方法返回一个 Channel 对象。在 Context 被取消时,这个channel 会被关闭。cancel、timeout、deadline 都可能导致Done被关闭。Done被关闭的时候,可以通过 ctx.Err() 获取错误信息。
  • Deadline 方法会返回这个 Context 被取消的截止日期。如果没有设置则第二个返回值ok是 false。
  • Value 返回此 ctx 中和指定的 key 对应的 value。

context 包中有两个常用的方法:

  • context.Background() 一般会用来创建根Context;该方法返回一个空Context;没有值。
  • context.TODO() 如果不清楚该用哪个Context,或不知道要传递一些什么上下文信息的时候可以使用

Context使用规约

  • 1、函数使用 Context作为参数的时候会把context作为第一个参数。
  • 2、不要使用 nil 当做 Context 类型的参数值,可以使用 context.Background()
  • 3、不要将上下文存储在结构类型内;而是将Context显式的透传给每个需要它的函数。
  • 4、key 的类型不应该是字符串类型或者其它内建类型。使用WithValue时,key 的类型应该是自己定义的类型或者struct{}。
  • 5、使用WithCancel、WithDeadline、WithTimeout或WithValue替换上下文。
  • 6、取消上下文时,从中派生的所有上下文也将被取消。

举个例子

使用 Context 来取消一个 goroutine 的运行,goroutine 需要尝试检查 Context 的 Done 是否关闭


package main

import (
	"context"
	"fmt"
	"time"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		defer func() {
			fmt.Println("this goroutine exit !!!")
		}()
		for {
			select {
			case <-ctx.Done():
				return
			default:
				fmt.Println("do something")
				time.Sleep(time.Second)
			}
		}
	}()
	time.Sleep(3 * time.Second)
	cancel()
	time.Sleep(2 * time.Second)
}
wx

关注公众号领取Go学习资料

wx

洋葱小店

©2017-2023 鲁ICP备17023316号-1 Powered by Hugo