Context

Context(context.go)

源码中我们可以得知有 context 是一个 interface,

type Context interface {
  Deadline() (deadline time.Time, ok bool)
  Done() <-chan struct{}
  Err() error
  Value(key any) any
}
func Background() Context
func TODO() Context
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key, val interface{}) Context

Deadline 方法需要返回当前 Context 被取消的时间,也就是完成工作的截止时间(deadline);

Done 方法需要返回一个 Channel,这个 Channel 会在当前工作完成或者上下文被取消之后关闭,多次调用 Done 方法会返回同一个 Channel;

Value 方法会从 Context 中返回键对应的值,对于同一个上下文来说,多次调用 Value 并传入相同的 Key 会返回相同的结果,该方法可用于传递跨 API 和进程间跟请求域的数据;

Background
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
	return background
}

示例代码

func main() {
	ctx := context.Background()
	sleepAndTalk(ctx, 5*time.Second, "hello")
}

func sleepAndTalk(ctx context.Context, d time.Duration, msg string) {
	select {
	case <-ctx.Done():
		fmt.Println("done")
	case <-time.After(d):
		fmt.Println(msg)
	}
}

Background()和 TODO()

Background()常用于初始化以及测试代码,作为 top-level 的 context。

TODO(),没有什么具体含义,但是又必须传递 ctx 的时候可以使用。

二者的共同点都是,没有 deadling, 没有 value, 没有 cancle
的 empty context

WithCancle
func main() {
	ctx := context.Background()
	ctx, cancle := context.WithCancel(ctx)
	// 1. 用户输入信息后context 执行cancle, 2022-11-21-22:54 控制台输出context deadline exceeded
	// go func() {
	// 	s := bufio.NewScanner(os.Stdin)
	// 	s.Scan()
	// 	cancle()
	// }()
	// 2. 1s之后取消,然后控制台输出 context deadline exceeded
	// go func() {
	// 	time.Sleep(time.Second)
	// 	cancle()
	// }()
	// 3. 或者可以使用time.afterfunc 同2方法一样效果
	time.AfterFunc(time.Second, cancle)
	sleepAndTalk(ctx, 5*time.Second, "hello")
}

func sleepAndTalk(ctx context.Context, d time.Duration, msg string) {
	select {
	case <-ctx.Done():
		fmt.Println(ctx.Err())
	case <-time.After(d):
		fmt.Println(msg)
	}
}

withTimeOut

func main() {
	ctx := context.Background()
	ctx, cancle := context.WithTimeout(ctx, time.Second)
	defer cancle()
	sleepAndTalk(ctx, 5*time.Second, "hello")
}

func sleepAndTalk(ctx context.Context, d time.Duration, msg string) {
	select {
	case <-ctx.Done():
		fmt.Println(time.Now().Format("2006-01-02-15:04"), "context cancled")
	case <-time.After(d):
		fmt.Println(msg)
	}
}

std: 2022-11-21-22:59 context cancled
withValue
func Decorate(f http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()
		// 随机 63 位整数作为 int64。
		id := rand.Int63()
		ctx = context.WithValue(ctx, reqIdkey, id)
		r = r.WithContext(ctx)
		f(w, r)
	}
}

整个代码参考以 http server、client、log
server
client
http_log

你可能感兴趣的:(Go语言,go)