Golang context.WithValue:如何添加几个键值对 [英] Golang context.WithValue: how to add several key-value pairs
问题描述
context
包可以将请求特定的数据传递给请求处理函数堆栈< pre $
func WithValue(父上下文,键,val接口{})上下文
这将创建一个新的 Context
,它是父级副本并包含可以用键访问的值val。
如果我想在 Context
中存储几个键值对,我该如何继续?我应该多次呼叫 WithValue()
,每次将从我上次调用中接收到的 Context
传递给 WithValue()
?这看起来很麻烦。
或者我应该使用一个结构并将所有的数据放在那里,s.t.我需要只传递一个值(这是结构),从中可以访问所有其他值?
或者是否有一种方法可以将几个键值对 WithValue()
?
您正在寻找的答案取决于您希望如何使用存储在上下文中的值。
context.Context
是一个不可变的对象,只能使用键值对扩展它通过复制它并将新的键值添加到副本中(这是在引擎盖下完成的,由 context
包)。
您是否希望其他处理程序能够通过以下方式访问所有值:以透明的方式键入?然后将所有内容添加到循环中,始终使用最后一个操作的上下文。
这里需要注意的一点是 context.Context
不会在引擎盖下使用
map
来存储键值对,这可能听起来令人惊讶,但如果您想到它肯定是不可变和安全的并发使用。
使用 map
例如,如果您有很多键值对,并且需要通过键 fast 查找值,则分别添加每个值将导致<$ c $其中 Value()
方法的c> Context 会很慢。在这种情况下,如果您将所有键值对添加为单个 map
值(可通过 Context.Value()
,其中的每个值都可以通过 O(1)
时间中的关联键查询。注意,这对于并发使用来说并不安全,因为映射可能会从并发goroutine中修改。
使用 struct
如果您使用 Context.Value()
访问这个结构会返回一个结构体的副本,所以它对于并发使用是安全的(每个goroutine只能得到一个不同的副本) ,但是如果你有许多键值对,每次有人需要单个字段时,这会导致不必要的大型结构副本。
使用混合解决方案解决方案
混合解决方案可以将所有键值对一个 这是它的样子: 使用它: 输出(在去游乐场试试): 并不重要(或者你有相对较少的键值对),我会分开添加每一个。 With Go's This creates a new How do I proceed if I want to store several key-value pairs in a Or is there a way of passing several key-value pairs to You pretty much listed your options. The answer you're seeking for depends on how you want to use the values stored in the context. Do you want further handlers to be able to access all the values by key in a transparent way? Then add all in a loop, using always the context of the last operation. One thing to note here is that the Using a So for example if you have a lot of key-value pairs and need to lookup values by keys fast, adding each separately will result in a Using a If you'd use a big Using a hybrid solution A hybrid solution could be to put all your key-value pairs in a This is how it could look like: Using it: Output (try it on the Go Playground): If performance is not critical (or you have relatively few key-value pairs), I'd go with adding each separately. 这篇关于Golang context.WithValue:如何添加几个键值对的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! map
,并为这个地图创建一个封装结构,隐藏 map
(未导出的字段),并只提供一个获取地图中存储的值。只将这个包装添加到上下文中,你为多个goroutines( map
是未导出的)保留安全的并发访问权限,但是没有大数据需要被复制( map
值是没有键值数据的小描述符),并且仍然是 fast 最终你会索引一张地图)。
类型值结构{
m map [string] string
}
func(v值)获取(键字符串)字符串{
return vm [key]
}
v:=值{map [string] string {
1:one,
2:two,
$}
c:= context.Background()
c2:= context.WithValue(c,myvalues,v)
fmt.Println (c2.Value(myvalues)。(Values).Get(2))
two
context
package it is possible to pass request-specific data to the stack of request handling functions usingfunc WithValue(parent Context, key, val interface{}) Context
Context
which is a copy of parent and contains the value val which can be accessed with key.Context
? Shall I call WithValue()
several times, each time passing the Context
received from my last call to WithValue()
? This appears cumbersome.
Or shall I use a struct and put all my data there, s.t. I need to pass only one value (which is the struct), from which all others can be accessed?WithValue()
?context.Context
is an immutable object, "extending" it with a key-value pair is only possible by making a copy of it and adding the new key-value to the copy (which is done under the hood, by the context
package).context.Context
does not use a map
under the hood to store the key-value pairs, which might sound surprising at first, but not if you think about it must be immutable and safe for concurrent use.map
Context
whose Value()
method will be slow. In this case it's better if you add all your key-value pairs as a single map
value, which can be accessed via Context.Value()
, and each value in it can be queried by the associated key in O(1)
time. Know that this will not be safe for concurrent use though, as a map may be modified from concurrent goroutines.struct
struct
value having fields for all the key-value pairs you want to add, that may also be a viable option. Accessing this struct with Context.Value()
would return you a copy of the struct, so it'd be safe for concurrent use (each goroutine could only get a different copy), but if you have many key-value pairs, this would result in unnecessary copy of a big struct each time someone needs a single field from it.map
, and create a wrapper struct for this map, hiding the map
(unexported field), and provide only a getter for the values stored in the map. Adding only this wrapper to the context, you keep the safe concurrent access for multiple goroutines (map
is unexported), yet no big data needs to be copied (map
values are small descriptors without the key-value data), and still it will be fast (as ultimately you'll index a 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"))
two