» Go语言快速入门 » 1. 基础篇 » 1.9 上下文

上下文

在Go语言中,context 包提供了一种在API之间和进程之间传递截止时间、取消和其他请求范围值的方式。 它是一种在函数和 Go 协程之间以清晰高效的方式传递取消信号、超时和截止时间的机制。

context 包包括 Context 类型以及用于创建和处理上下文值的各种函数。

Context 类型

Context 类型表示操作的上下文。在需要携带截止时间、取消或其他请求范围值的函数中,它通常是第一个参数。

import "context"

func example(ctx context.Context) {
    // ...
}

创建上下文

context 包提供了多个用于创建新上下文或从现有上下文派生新上下文的函数。

  • context.Background(): 返回空的上下文。通常用作创建其他上下文的起点。
  • context.TODO(): 与Background类似,当需要传递上下文但没有特定信息可提供时使用。
  • context.WithCancel(parent): 返回一个上下文和取消函数。取消函数可用于取消上下文。
  • context.WithTimeout(parent, timeout): 返回一个具有超时的上下文。
  • context.WithDeadline(parent, deadline): 返回一个具有特定截止时间的上下文。
  • context.WithValue(parent, key, value): 返回与其关联的带有键值对的上下文。通常用于携带请求范围值。

使用上下文传递值

WithValue 函数用于将键值对与上下文关联。使用此功能时注意避免创建深度嵌套的上下文。

package main

import (
	"context"
	"fmt"
)

func main() {
	type favContextKey string

	f := func(ctx context.Context, k favContextKey) {
		if v := ctx.Value(k); v != nil {
			fmt.Println("found value:", v)
			return
		}
		fmt.Println("key not found:", k)
	}

	k := favContextKey("language")
	ctx := context.WithValue(context.Background(), k, "Go")

	f(ctx, k) // => found value: Go
	f(ctx, favContextKey("color")) // => key not found: color
}

提供的键必须是可比较的,并且不可是字符串或任何其他内置类型,以避免在使用上下文的包之间发生冲突。使用 WithValue 的用户应该为键定义自己的类型。

在 Go 协程中使用上下文

Goroutines1 可以与 Context 关联。当 Context 被取消或超时时,与其关联的所有 goroutine 都会收到取消通知。

func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            // 处理取消
            return
        default:
            // 执行一些工作
        }
    }
}

代码挑战

编写一个模拟执行任务的 WorkerWithTimeout 函数。 该函数应使用 context 包实现任务的超时限制。
如果任务花费的时间超过指定的超时时间,函数应返回超时错误。

Footnotes

  1. Goroutine 是由 Go 运行时管理的轻量级线程,它可以并发执行函数。

Loading...
> 此处输出代码运行结果
上页
下页