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 压测时,并发量过高时,响应时间出现尖刺
  • ¥15 关于vmprotect3.8.4虚拟文件一项
  • ¥15 在不用IT调试的情况下怎样能连外网
  • ¥20 C#调用虚拟键盘TabTip.exe
  • ¥15 Qt4代码实现下面的界面
  • ¥15 CCS离散化传递函数与仿真不一致
  • ¥15 prism提示我reinstall prism 如何解决
  • ¥15 asp.core 权限控制怎么做,需要控制到每个方法
  • ¥20 while循环中OLED显示中断中的数据不正确
  • ¥15 这个视频里的stm32f4代码是怎么写的