如何避免Go与julien schmidt的路由器中的全局变量?

时间:2018-03-08 18:26:30

标签: go

我正在使用Go开发RESTful API,但由于应用程序配置,身份验证等原因,我有很多全局变量。

由于受欢迎的推荐,我正在使用Julien Schmidt的httprouter,我正在寻找避免全局变量的可行方法。

以下是一些代码。

我正在使用中间件来验证使用gorrila / securecookie的用户。

func AuthMiddleware(handler httprouter.Handle, isLoggedIn bool) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {if isLoggedIn {
            currUser, err := GetCurrentUser(r)

            if currUser.Username != "" {
                handler(w, r, ps)
                return
            }

            responseWriter(w, false, "User not logged in", nil)
            return
        }
        handler(w, r, ps)
    }
}

在此之后,我希望能够在请求转发到的处理程序中使用currUser对象,而不是再次调用GetCurrentUser

func foobar(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
    var currQuestion CurrQuestions

    err = Db.db.Raw("SELECT * FROM users WHERE U.user_id = ?", currUser.UserID).Find(&currQuestion).Error
    if err != nil {
        responseWriter(w, false, "Internal Server Error", "")
        return
    }
    responseWriter(w, true, "", GameData{})
}

1 个答案:

答案 0 :(得分:0)

您可以使用上下文包。存储在上下文中的值只能在当前控制器中访问。在您的中间件(最后)执行以下操作:

ctx := context.WithValue(r.Context(), "User", user)
r = r.WithContext(ctx)
handler(w, r, ps)

现在您可以在处理程序中获取此值:

user, ok := r.Context().Value("User").(<type of your user struct>)

字符串“User”是用于保存值的键。你可以随意改变它,但const是个好主意。

如果oktrue,则已提取用户且类型正确。如果okfalse,则表示用户未设置或类型错误。