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"))
}
但我不知道如何设定价值。这对我来说不是很直观,我真的不明白该怎么做。
答案 0 :(得分:2)
请参阅" Exploring the context package",使用WithValue
以及与请求相关联的上下文:
中间件
Go中的中间件指的是一个包装多路复用器的http处理程序。有几个第三方中间件解决方案(如negroni),但实际上标准库支持非常相似的模式。在请求中使用Context允许我们在请求中保存数据。
请参阅invocation和definition的示例代码。
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建议