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.

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

报告相同问题?

悬赏问题

  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)