如何向我的处理程序传递参数

78

我试图将我的数据库对象传递给处理程序,而不是使用全局对象。但我不知道这是否可能,我正在使用Gorilla Mux包,我可以看到它将闭包作为第二个参数。

// https://github.com/gorilla/mux/blob/master/mux.go#L174
// HandleFunc registers a new route with a matcher for the URL path.
// See Route.Path() and Route.HandlerFunc().
func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,
    *http.Request)) *Route {
    return r.NewRoute().Path(path).HandlerFunc(f)
}

这样就定义了我可以使用的参数,理想情况下,我希望有第三个参数,就像这样。

// In my main
router.HandleFunc("/users/{id}", showUserHandler).Methods("GET")

func showUserHandler(w http.ResponseWriter, r *http.Request, db *gorm.DB) {
    fmt.Fprintf(w, "We should fetch the user with id %s", vars["id"])
}

有没有解决方法?还是说我需要一个全局的 db 对象?我是 Go 的新手,请详细解释一下可能的答案。


2
https://dev59.com/0IPba4cB1Zd3GeqPxtSu#26106655 可以给你一些想法。 - VonC
@VonC 我实际上尝试了http://simonsdotnet.wordpress.com/2014/09/06/extending-gos-http-handlers/,但发现它与Gorilla不兼容,因为http包只需要ServeHTTP,而Gorilla需要具有特定参数的func。当然我可能是错的。 - MartinElvar
1个回答

137

欢迎来到 Go。

使用全局变量和特别数据库对象是可以接受的。

但是,如果您不喜欢这种方式,有几种解决方法。例如,您可以创建一个结构体并在其中定义您的showHandler

type Users struct {
    db *gorm.DB
}

func (users *Users) showHandler(w http.ResponseWriter, r *http.Request) {
    //now you can use users.db
}
func (users *Users) addHandler(w http.ResponseWriter, r *http.Request) {
    //now you can use users.db
}

// setup
users := &Users{db: createDB()}
router.HandleFunc("/users/{id}", users.showHandler).Methods("GET")
router.HandleFunc("/users/new", users.addHandler)
//etc

另一种方法是创建一个包装函数:

db := createDB()
router.HandleFunc("/users/{id}", func(w http.ResponseWriter, r *http.Request) {
    showUserHandler(w, r, db)
}).Method("GET")

谢谢OneOfOne。我的想法是,我想以更DI的方式来完成它,也许我想太多了。你认为哪种解决方案最干净? - MartinElvar
@MartinElvar 对于数据库连接,我会说全局变量是可以的。如果你想要特定的变量只能被一组特定的函数使用,那么结构体解决方案是更好的选择。 - OneOfOne
1
@MartinElvar 请记住,虽然大多数数据库处理程序都是安全的并发处理,但其他所有内容都不是,因此,如果您在一个处理程序中设置了一个变量并在另一个处理程序中获取它,则必须使用某种锁定机制。 - OneOfOne
1
非常感谢您的帮助,谢谢 @OneOfOne :) - MartinElvar
7
我会选择提出的“包装”方法。我经常看到它被用于将处理程序与“中间件”服务进行包装。 - Sridhar
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接