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.

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

报告相同问题?

悬赏问题

  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId
  • ¥15 delphi7 HMAC_SHA256方式加密
  • ¥15 关于#qt#的问题:我想实现qcustomplot完成坐标轴
  • ¥15 下列c语言代码为何输出了多余的空格