如何使用 context.WithValue() 存储 context.CancelFunc 类型的值?

Posted

技术标签:

【中文标题】如何使用 context.WithValue() 存储 context.CancelFunc 类型的值?【英文标题】:How to store a value of type context.CancelFunc using context.WithValue()? 【发布时间】:2021-11-25 22:58:18 【问题描述】:

要将string类型数据存储在ctx中,key&value都需要使用类型定义,如下图:

    // Sample program to show how to store and retrieve
    // values from a context.
    package main
    
    import (
        "context"
        "fmt"
    )
    
    // TraceID represents the trace id.
    type TraceID string
    
    // TraceIDKey is the type of value to use for the key. The key is
    // type specific and only values of the same type will match.
    type TraceIDKey int
    
    func main() 
    
        // Create a traceID for this request.
        traceID := TraceID("f47ac10b-58cc-0372-8567-0e02b2c3d479")
    
        // Declare a key with the value of zero of type userKey.
        const traceIDKey TraceIDKey = 0
    
        // Store the traceID value inside the context with a value of
        // zero for the key type.
        ctx := context.WithValue(context.Background(), traceIDKey, traceID)
    
        // Retrieve that traceID value from the Context value bag.
        if uuid, ok := ctx.Value(traceIDKey).(TraceID); ok 
            fmt.Println("TraceID:", uuid)
        
    
        // Retrieve that traceID value from the Context value bag not
        // using the proper key type.
        if _, ok := ctx.Value(0).(TraceID); !ok 
            fmt.Println("TraceID Not Found")
        
    

如何使用context.WithValue() api 存储context.CancelFunc 类型的值?

【问题讨论】:

遵循您用于存储 traceID 的模式。 您可以使用任何类型的键和值。我怀疑您是否需要在上下文中存储取消功能,这是一种设计气味。如果您描述了您的目标,也许我们可以提出更好的替代方案。 【参考方案1】:

你是部分正确的。您应该为您的上下文键使用定制类型而不是内置类型,以使冲突变得不可能。这种类型应该不被导出,除非你希望其他包能够读/写你的上下文键。但是,该值可以是您喜欢的任何值,例如:

package main

import (
    "context"
    "fmt"
)

type contextKey int

const (
    traceIDKey contextKey = iota
    aFunctionWhyNot
)

func main() 

    // Create a traceID for this request.
    traceID := "f47ac10b-58cc-0372-8567-0e02b2c3d479"

    // Store the traceID value inside the context with a value of
    // zero for the key type.
    ctx := context.WithValue(context.Background(), traceIDKey, traceID)

    // Retrieve that traceID value from the Context value bag.
    if uuid, ok := ctx.Value(traceIDKey).(string); ok 
        fmt.Println("TraceID:", uuid)
    

    // Or a function
    ctx = context.WithValue(ctx, aFunctionWhyNot, func()  fmt.Println("lol, I'm a function on a context") )

    // Call it maybe
    if f, ok := ctx.Value(aFunctionWhyNot).(func()); ok 
        f()
    

【讨论】:

【参考方案2】:

您可以像存储任何其他值一样在上下文中存储函数:

type cancelFuncKeyType struct
var cancelFuncKey =cancelFuncKeyType

...
newctx:=context.WithValue(oldctx,cancelFuncKey,cancelFunc)


cFunc:=newctx.Value(cancelFuncKey).(context.CancelFunc)

【讨论】:

以上是关于如何使用 context.WithValue() 存储 context.CancelFunc 类型的值?的主要内容,如果未能解决你的问题,请参考以下文章

golang-context

golang-context

golang-context

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话