在Go中使用上下文检索切片值时是否需要互斥锁读取锁定?

时间:2017-03-20 00:07:05

标签: go

我一直在阅读中间件中的上下文和传递值。由于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"))
}

锁是否必要?

1 个答案:

答案 0 :(得分:0)

您担心数据竞争。 golang博客上有一些有用的东西:

  

数据竞争是最常见和最难调试的类型之一   并发系统中的错误。两个goroutines发生数据竞争   同时访问相同的变量和至少一个访问   是写作。

race detector blog entry

的介绍

因此,如果您不确定是否可以运行竞赛检测器。因为它并不复杂。只需设置标志-race,然后将检查是否存在数据竞争。

当您正常使用上下文时,您不需要锁定,因为通过所有调用,并且对于每个新调用,内存中都会有另一个地址。

如果您总是从变量中读取,则不需要将其锁定,因为这样的值永远不会改变。