登录
首页 >  Golang >  Go问答

context.WithValue:如何添加几个键值对

来源:Golang技术栈

时间:2023-04-30 18:14:15 373浏览 收藏

亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《context.WithValue:如何添加几个键值对》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下golang,希望所有认真读完的童鞋们,都有实质性的提高。

问题内容

使用 Go 的context包,可以将特定于请求的数据传递给请求处理函数的堆栈,使用

func WithValue(parent Context, key, val interface{}) Context

这将创建一个新的Context,它是 parent 的副本,并包含可以使用键访问的值 val。

如果我想在 a 中存储多个键值对,我该如何进行Context?我应该打WithValue()几次电话,每次都将Context我上次打电话时收到的信息传递给WithValue()? 这看起来很麻烦。
或者我应该使用一个结构并将我的所有数据放在那里,我只需要传递一个值(即结构),可以从中访问所有其他值?

或者有没有办法将几个键值对传递给WithValue()

正确答案

你几乎列出了你的选择。您正在寻找的答案取决于您希望如何使用存储在上下文中的值。

context.Context是一个不可变的对象,只有通过复制它并将新的键值添加到副本中(这是由包在后台完成的),才能用键值对“扩展”它context

您是否希望其他处理程序能够以透明的方式通过键访问所有值?然后在一个循环中添加所有内容,始终使用最后一个操作的上下文。

这里需要注意的一点是,context.Context它不使用 amap来存储键值对,这乍一看可能令人惊讶,但如果您认为它必须是不可变的并且可以安全地并发使用,那就不会了。

用一个map

因此,例如,如果您有很多键值对并且需要通过键 快速 查找值,则单独添加每个将导致ContextwhoValue()方法会很慢。在这种情况下,最好将所有键值对添加为单个map值,可以通过 访问Context.Value(),并且其中的每个值都可以通过关联的键O(1)及时查询。但是要知道这对于并发使用是不安全的,因为可以从并发 goroutines 修改 map。

用一个struct

如果您要struct为要添加的所有键值对使用具有字段的大值,那也可能是一个可行的选择。访问这个结构Context.Value()会返回一个结构的副本,所以并发使用是安全的(每个 goroutine 只能得到一个不同的副本),但是如果你有很多键值对,这会导致不必要的副本每次有人需要一个字段时,一个大结构。

使用 混合 解决方案

混合 解决方案可能是将所有键值对放在 a 中map,并为此映射创建一个包装结构,隐藏map(未导出的字段),并仅为存储在映射中的值提供一个 getter。仅将这个包装器添加到上下文中,您可以保持多个 goroutine的 安全并发访问map(未导出),但 不需要复制大数据map值是没有键值数据的小描述符),它仍然会 很快 (因为最终你会索引一张地图)。

这就是它的样子:

type Values struct {
    m map[string]string
}

func (v Values) Get(key string) string {
    return v.m[key]
}

使用它:

v := Values{map[string]string{
    "1": "one",
    "2": "two",
}}

c := context.Background()
c2 := context.WithValue(c, "myvalues", v)

fmt.Println(c2.Value("myvalues").(Values).Get("2"))

输出(在Go Playground上试试):

two

如果性能不重要(或者您的键值对相对较少),我会单独添加每个。

到这里,我们也就讲完了《context.WithValue:如何添加几个键值对》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于golang的知识点!

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>