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

在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?

  • 写回答

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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料