你在描述上下文。
原来是
gorilla context package
,它提供一个伪全局上下文对象-本质上是
map[interface{}]interface{}
具有对中间件/控制器/数据层堆栈中的所有参与者都可用的内部引用。
看这个除了从
an excellent guide to the package
(全部归功于作者马特·西尔弗洛克)。
type contextKey int
// Define keys that support equality.
const csrfKey contextKey = 0
const userKey contextKey = 1
var ErrCSRFTokenNotPresent = errors.New("CSRF token not present in the request context.")
// We'll need a helper function like this for every key:type
// combination we store in our context map else we repeat this
// in every middleware/handler that needs to access the value.
func GetCSRFToken(r *http.Request) (string, error) {
val, ok := context.GetOk(r, csrfKey)
if !ok {
return "", ErrCSRFTokenNotPresent
}
token, ok := val.(string)
if !ok {
return "", ErrCSRFTokenNotPresent
}
return token, nil
}
// A bare-bones example
func CSRFMiddleware(h http.Handler) http.Handler {
return func(w http.ResponseWriter, r *http.Request) {
token, err := GetCSRFToken(r)
if err != nil {
http.Error(w, "No good!", http.StatusInternalServerError)
return
}
// The map is global, so we just call the Set function
context.Set(r, csrfKey, token)
h.ServeHTTP(w, r)
}
}
在大猩猩套餐诞生后,
context package
已添加到标准库。它略有不同,因为上下文不再是伪全局的,而是从一个方法传递到另一个方法。在此情况下,上下文将附加到初始请求-可通过
request.Context
是的。处理程序下面的层可以接受上下文值作为其签名的一部分,并从中读取值。
下面是一个简单的例子:
type contextKey string
var (
aPreSharedKey = contextKey("a-preshared-key")
)
func someHandler(w http.ResponseWriter, req *http.Request) {
ctx := context.WithValue(req.Context, aPreSharedKey, req.Header.Get("required-header"))
data, err := someDataLayerFunction(ctx)
if err != nil {
fmt.Fprintf(w, "uhoh", http.StatusBadRequest)
return
}
fmt.Fprintf(w, data, http.StatusOK)
}
func someDataLayerFunction(ctx context.Context) (string, error) {
val, ok := ctx.Value(aPreSharedKey).(string)
if !ok {
return nil, errors.New("required context value missing")
}
return val
}
要了解更多细节和一个不那么做作的例子,请查看google的
excellent blog on the context package's use.