Go context 上下文

发布时间: 更新时间: 总字数:405 阅读时间:1m 作者: IP上海 分享 网址

golang context 用来传递上下文的信息,该类型可跨 API 和进程间传输截止日期、取消信号和其他请求范围值,一般用作函数的第一个参数。

介绍

Context由一个接口和几个实现组成

Context 接口

参考

type Context interface {
	Deadline() (deadline time.Time, ok bool)
	Done() <-chan struct{}
	Err() error
	Value(key any) any
}

初始化方法包括:

# 创建 context
func Background() Context
func TODO() Context  // 不确定应该使用哪种上下文时使用

# context 衍生
func WithValue(parent Context, key, val any) Context
func WithoutCancel(parent Context) Context

实现

  • AfterFunc(ctx, f)
  • Cause(c)
  • WithCancel(parent)
  • WithCancelCause(parent)
  • WithDeadline(parent, d)
  • WithDeadlineCause(parent, d, cause)
  • WithTimeout(parent, timeout)
  • WithTimeoutCause(parent, timeout, cause)

示例

demo1

type contextKey string
const userIDKey contextKey = "userid"
...
ctx := context.WithValue(r.Context(), userIDKey, claimsWithPayload.Id)
...
a := r.Context().Value(userIDKey).(string)

说明:

  • 若不定义 contextKey 会报错 should not use built-in type string as key for value; define your own type to avoid collisions (SA1029)

select 配合使用

package main

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

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
	defer cancel()

	select {
	case <-time.After(1 * time.Second):
		fmt.Println("Done")
	case <-ctx.Done():
		fmt.Println(ctx.Err())
	}
}
  • 执行结果
context deadline exceeded

经常与 for + goroutine + select + chan 一起使用

WithCancel

package main

import (
	"context"
	"fmt"
)

func main() {
	// gen generates integers in a separate goroutine and
	// sends them to the returned channel.
	// The callers of gen need to cancel the context once
	// they are done consuming generated integers not to leak
	// the internal goroutine started by gen.
	gen := func(ctx context.Context) <-chan int {
		dst := make(chan int)
		n := 1
		go func() {
			for {
				select {
				case <-ctx.Done():
					return // returning not to leak the goroutine
				case dst <- n:
					n++
				}
			}
		}()
		return dst
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // cancel when we are finished consuming integers

	for n := range gen(ctx) {
		fmt.Println(n)
		if n == 5 {
			break
		}
	}
}

参考

  1. https://pkg.go.dev/context
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数