Golang 上下文。上下文传播

标签 go

我想问一下我们应该如何处理 Golang 中的上下文传播问题。

我的应用程序是一个 HTTP JSON API 服务器。

我会将上下文用作信息数据的容器(例如,请求 ID,我从请求或流程中解压的一些内容)。

最愚蠢的优势之一是车辆数据和标签可用于统计和记录。例如。能够在每个日志行添加我拥有的所有包中的事务 ID

我面临的问题如下:

func handleActivityY(w http.ResponseWriter, r *http.Request) {
    info, err := decodeRequest(r)
    ...
    stepOne, err := stepOne(r.Context(), info)
    ...
    stepTwo, err := stepTwo(r.Context(), stepOne)
    ...
}

这种设计的问题在于上下文是一个不可变的实体(每次我们添加一些东西或设置新的超时时,我们都会有一个新的上下文)。

除非在每次函数调用时返回上下文(连同返回值,如果有的话和错误),否则无法传播上下文。

完成这项工作的唯一方法是:

func handleActivityY(w http.ResponseWriter, r *http.Request) {
    ctx, info, err := decodeRequest(r)
    ...
    ctx, stepOne, err := stepOne(ctx, info)
    ...
    ctx, stepTwo, err := stepTwo(ctx, stepOne)
    ...
}

我已经使用 context.Context 参数污染了我包中的几乎所有函数。在我看来,除了其他参数之外还返回它似乎有点过分了。

真的没有其他更优雅的方式吗?

我目前正在使用 gin 框架,它有自己的上下文并且是可变的。我不想为此添加对 Gin 的依赖。

最佳答案

在上下文管道的早期,添加一个指向数据结构的可变指针:

type MyData struct {
    // whatever you need
}

var MyDataKey = /* something */

ctx, cancel := context.WithValue(context.Background(), MyDataKey, &MyData{})

然后在需要修改数据结构的方法中,这样做:

data := ctx.Value(MyDataKey)
data.Foo = /* something */

有关并发访问安全的所有常规规则均适用,因此如果多个 goroutine 可以同时读取/设置您的数据值,您可能需要使用互斥体或其他保护机制。

关于Golang 上下文。上下文传播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49180425/

相关文章:

go - 如何在grpc go中实现非阻塞客户端?

go - Fprint/Fprintf与conn.Write之间的区别

xml - 如何从 XML 元素中获取文本(结构标签)?

mysql - 如何测试mysql的insert方法

pointers - Go 中的指针解除引用是如何工作的?

go - Viper AddConfigPath 仅在当前文件夹中查找文件 "."

go - 通过引用传递数组到采用数组的函数的任何方法吗?

Goroutines 破坏了程序

go - 复制对指针或按值的引用

linux - 如何正确计算TCP数据包校验和?