0Pricing
Go Academy · 课时

WithDeadline 与 WithValue

绝对截止时间与传递请求范围内的值

WithDeadline 与 WithValue 是 CoddyKit 上的免费 Go Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

context.WithDeadline

WithDeadline 会创建一个在绝对时间点取消的上下文。如果父上下文已有更早的截止时间,则以父上下文的截止时间为准。

deadline := time.Now().Add(10 * time.Second)
ctx, cancel := context.WithDeadline(parent, deadline)
defer cancel()

WithTimeout 与 WithDeadline

WithTimeout(parent, d) 等价于 WithDeadline(parent, time.Now().Add(d))。当您有绝对过期时间时(例如来自传入 RPC 标头),请使用 WithDeadline。

读取截止时间

使用 ctx.Deadline() 检查任意上下文的截止时间。布尔值表示是否存在截止时间。

if deadline, ok := ctx.Deadline(); ok {
    fmt.Println("expires at:", deadline)
}

context.WithValue

WithValue 会将一个键值对附加到上下文中。下游代码可以使用 ctx.Value(key) 获取它。

type ctxKey string
const userKey ctxKey = "user"

ctx := context.WithValue(parent, userKey, currentUser)

func getUser(ctx context.Context) *User {
    u, _ := ctx.Value(userKey).(*User)
    return u
}

防止键冲突

请为键使用未导出的包专用类型,以防止不同包之间发生冲突。不要直接使用内置类型(string、int)作为上下文键。

// Bad: string key can collide
ctx = context.WithValue(ctx, "user", u)
// Good: package-scoped type
type userKeyType struct{}
ctx = context.WithValue(ctx, userKeyType{}, u)

上下文中应存储什么

仅存储跨越 API 边界的请求作用域值:追踪 ID、认证令牌和请求 ID。不要存储可选的函数参数或可变状态。

WithValue 的性能

ctx.Value 会沿上下文链向上进行线性查找。请避免在每个上下文中存储大量值;如果有多个值,请将它们分组到一个结构体中。

type RequestMeta struct {
    UserID  int
    TraceID string
}
type metaKey struct{}
ctx = context.WithValue(ctx, metaKey{}, RequestMeta{...})

通过中间件传递值

HTTP 中间件是将请求元数据附加到上下文,并在处理程序中获取这些元数据的规范位置:

func Auth(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        user := authenticate(r)
        ctx := context.WithValue(r.Context(), userKey, user)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

r.WithContext

使用 r.WithContext(ctx) 替换 HTTP 请求的上下文。此操作会创建请求的浅复制并使用新的上下文,同时不修改原请求。

截止时间传递

当网关在上下文中设置截止时间并将请求传递给下游时,所有接受该上下文的服务都会自动遵守截止时间,无需显式的超时逻辑。

上下文链

每个 WithValue、WithCancel 和 WithTimeout 都会将父上下文包装在一个新节点中。ctx.Value 会遍历这条链,直到找到该键,或到达返回 nil 的根上下文。

快速检查

为什么上下文键应使用未导出的包专用类型?

回顾:WithDeadline 与 WithValue

关键要点:

  • WithDeadline 在绝对时间取消;WithTimeout 使用相对时间
  • ctx.Deadline() 用于读取截止时间
  • WithValue 用于请求作用域的元数据;请使用带类型的未导出键
  • 将多个值分组到一个结构体中,以减少链的深度

常见问题解答

「WithDeadline 与 WithValue」课时是免费的吗?

是的 — 「WithDeadline 与 WithValue」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「WithDeadline 与 WithValue」这节课中我会学到什么?

绝对截止时间与传递请求范围内的值 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「WithDeadline 与 WithValue」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 为什么需要 context.Context
  2. WithCancel 与 WithTimeout
  3. WithDeadline 与 WithValue
  4. HTTP 与数据库调用中的上下文
← 返回 Go Academy