我一直在阅读中间件中的上下文和传递值。由于julienschmidt httprouter与http.Handler接口不兼容,我想我可以保存httprouter Params
,它是Param
的一部分
https://godoc.org/github.com/julienschmidt/httprouter#Params
并将其保存在上下文值中,稍后检索。
关于上下文的Go博客文章:https://blog.golang.org/context说:
Value允许Context携带请求范围的数据。那个数据必须是 可安全地同时使用多个goroutines。
我不知道这些数据是否安全。正如我所理解的那样,切片不是线程安全的,但在这种情况下,多个go例程如何访问数据呢?
我有一个处理程序将http.Handler转换为httprouter.Handle并保存httprouter.Params,以便我可以在http.HandlerFunc类型函数中使用这些参数。
type ctxKey string
var paramKey ctxKey = "params"
func paramHandler(h http.Handler) httprouter.Handle {
return httprouter.Handle(func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
ctx := context.WithValue(r.Context(), paramKey, ps)
h.ServeHTTP(w, r.WithContext(ctx))
})
}
var mutex sync.RWMutex
func params(r *http.Request) httprouter.Params {
// https://blog.golang.org/context
// "Value allows a Context to carry request-scoped data.
// That data must be safe for simultaneous use by multiple goroutines."
mutex.RLock()
value := r.Context().Value(paramKey)
mutex.RUnlock()
if ps, ok := value.(httprouter.Params); ok {
return ps
}
return httprouter.Params{}
}
在paramHandler中我设置了一个httprouter.Param片段的上下文值,在params(r * http.Request)函数中我收到了参数。
我的问题是,在paramHandler的上下文中保存params片段时是否需要写入锁定,并且在函数参数(* http.Request)中从上下文中检索params时读取锁定?
我计划检索这样的参数:
func getUser(w http.ResponseWriter, r *http.Request) {
ps := params(r)
fmt.Println(ps.ByName("id"))
}
锁是否必要?
答案 0 :(得分:0)
您担心数据竞争。 golang博客上有一些有用的东西:
的介绍数据竞争是最常见和最难调试的类型之一 并发系统中的错误。两个goroutines发生数据竞争 同时访问相同的变量和至少一个访问 是写作。
因此,如果您不确定是否可以运行竞赛检测器。因为它并不复杂。只需设置标志-race
,然后将检查是否存在数据竞争。
当您正常使用上下文时,您不需要锁定,因为通过所有调用,并且对于每个新调用,内存中都会有另一个地址。
如果您总是从变量中读取,则不需要将其锁定,因为这样的值永远不会改变。