我怎样才能使用Go的新上下文包,就像我会使用gorilla上下文库一样?

时间:2017-03-18 04:37:15

标签: go

Go已经推出了一个名为context的新软件包和最新版本(我认为Go 1.7)我们应该能够像gorilla / context软件包一样使用它:

http://www.gorillatoolkit.org/pkg/context

使用gorilla上下文,您可以非常轻松地设置和获取与请求,处理程序和中间件相关的变量。

在gorilla上下文中设置一个值非常简单:

func handleFunc(w http.ResponseWriter, r *http.Request) {
    context.Set(r, "foo", "bar")
}

要获得我们可以做的价值:

func handleFunc(w http.ResponseWriter, r *http.Request) {
    val := context.Get(r, "foo")
}

我知道我们可以在中间件中使用它,以便下一个中间件可以使用在以前的中间件中设置的变量。我希望能够使用Go上下文包。

我明白获取一个值非常简单:

func handleFunc(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.Context().Value("foo"))
}

但我不知道如何设定价值。这对我来说不是很直观,我真的不明白该怎么做。

1 个答案:

答案 0 :(得分:2)

请参阅" Exploring the context package",使用WithValue以及与请求相关联的上下文:

  

中间件

     

Go中的中间件指的是一个包装多路复用器的http处理程序。有几个第三方中间件解决方案(如negroni),但实际上标准库支持非常相似的模式。在请求中使用Context允许我们在请求中保存数据。

     

请参阅invocationdefinition的示例代码。

func putClientIPIntoContext(r *http.Request) context.Context {
    ci := r.RemoteAddr
    fwd := r.Header.Get("X-Forwarded-For")
    if fwd != "" {
        ci = fwd
    }
    ctx := context.WithValue(r.Context(), ClientIPKey, ci)
    return ctx
}
  

Context可以存储请求范围的变量   在编写“中间件”时它很有用,但它有点“反模式” - 它有点神奇,因为它不是类型安全的。

请参阅" Pitfalls of context values and how to avoid or mitigate them in Go"。

  

The example below仅显示如何使用上面的身份验证逻辑来​​验证用户在访问路径前缀为/dashboard/的任何网页时是否已登录。
  在允许用户访问路径前缀为/admin/的任何页面之前,可以使用类似的方法来验证用户是否为管理员。

func requireUser(next http.Handler) http.Handler {  
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    user := lookupUser(r)
    if user == nil {
      // No user so redirect to login
      http.Redirect(w, r, "/login", http.StatusFound)
      return
    }
    ctx := context.WithValue(r.Context(), "user", user)
    next.ServeHTTP(w, r.WithContext(ctx))
  })
}

func main() {  
  dashboard := http.NewServeMux()
  dashboard.HandleFunc("/dashboard/hi", printHi)
  dashboard.HandleFunc("/dashboard/bye", printBye)

  mux := http.NewServeMux()
  // ALL routes that start with /dashboard/ require that a 
  // user is authenticated using the requireUser middleware
  mux.Handle("/dashboard/", requireUser(dashboard))
  mux.HandleFunc("/", home)

  http.ListenAndServe(":3000", addRequestID(mux))
}

作为kostix条评论,请明智地使用背景信息,例如{" Dave Cheney"

中的Context is for cancelation建议