douzhuo1858
2017-03-20 00:07
浏览 82
已采纳

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

I have been reading about context and passing values in middlewares. Since the julienschmidt httprouter is not compatible with http.Handler interface I thought I could save the httprouter Params which is a slice of Param

https://godoc.org/github.com/julienschmidt/httprouter#Params

and save this in a context value and retrieve later.

The Go blog article on context: https://blog.golang.org/context says that:

Value allows a Context to carry request-scoped data. That data must be safe for simultaneous use by multiple goroutines.

I don't know if this data is safe. Slices are not thread safe as I understand, but how would multiple go routines access the data in this situation?

I have a handler that converts http.Handler to httprouter.Handle and saves the httprouter.Params so that I can use those params in http.HandlerFunc type functions.

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{}
}

In paramHandler I set the context value which is a slice of httprouter.Param, and in params(r *http.Request) function I receive the parameters.

My question is, do I need write locks when saving the slice of params in context in paramHandler, and read locks when retrieving the params from context as I have in the function param(*http.Request)?

I plan on retrieving the params like this:

func getUser(w http.ResponseWriter, r *http.Request) {
    ps := params(r)
    fmt.Println(ps.ByName("id"))
}

Are the locks necessary?

图片转代码服务由CSDN问答提供 功能建议

我一直在阅读有关上下文和在中间件中传递值的信息。 由于julienschmidt httprouter与http.Handler接口不兼容,我想我可以保存httprouter Params ,它是 Param https://godoc.org/github.com/julienschmidt/httprouter#Params

并将其保存在上下文值中,以供日后检索。

有关上下文的Go博客文章: https://blog.golang.org/context 表示:

值允许上下文携带请求范围的数据。 该数据必须是 安全的,才能被多个goroutine同时使用。

我不知道此数据是否安全。 据我了解,切片不是线程安全的,但是在这种情况下多个go例程将如何访问数据?

我有一个将http.Handler转换为httprouter.Handle并保存httprouter的处理程序 .param,以便我可以在http.HandlerFunc类型的函数中使用这些参数。

 类型ctxKey字符串
 
var paramKey ctxKey =“ params” 
 
func paramHandler(h  http.Handler)httprouter.Handle {
返回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互斥体同步RWMutex 
 
func参数(r * http.Request)httprouter.Params {\  n // https://blog.golang.org/context
 //“值允许Context携带请求范围的数据。
 //该数据必须可以安全地被多个goroutine同时使用。” 
互斥锁 .RLock()
 value:= r.Context()。Value(paramKey)
 Mutex.RUnlock()
如果ps,确定:= value。(httpr  outer.Params); 好的{
 return ps 
} 
返回httprouter.Params {} 
} 
   
 
 

在paramHandler中,我设置了上下文值,该值是httprouter的一部分 .param,并在params(r * http.Request)函数中接收参数。

我的问题是,在paramHandler中将参数切片保存在上下文中时,是否需要写锁, 并像我在函数param(* http.Request)中一样从上下文中检索参数时读锁?

我打算像这样检索参数: \ n

  func getUser(w http.ResponseWriter,r * http.Request){
 ps:= params(r)
 fmt.Println(ps.ByName(“ id”))
} \  n   
 
 

是否需要锁?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dousiyou1058 2017-03-20 05:43
    已采纳

    You are worried about a data race. Here is something helpful on the golang blog:

    Data races are among the most common and hardest to debug types of bugs in concurrent systems. A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.

    The introduction to the race detector blog entry

    So if you are not sure you can run the race detector. Because it is not complicated. Just set the flag -race and go will check if there is a data race.

    When you use context normally you don't need to lock, because is passed through all the calls and for every new call there will be another address inside the memory.

    If you always read from a variable you don't need to lock it, because then the value will never change.

    已采纳该答案
    打赏 评论

相关推荐 更多相似问题