我遇到了创建中间件的问题,该中间件将链接到其他路由并需要访问数据库,并且不确定如何解决此问题。
我将所有应用程序上下文存储在一个名为 func SomeHandler(appC *AppContext, next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
// Access the database using appC.db
// Logic that requires access to the database.
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
}
的结构中,包括数据库。我想创建一个看起来像这样的函数处理程序:
main.go
在someHandler := middleware.SomeHandler(&appC)
中,我尝试过:
not enough arguments in call to middleware.SomeHandler
但是,我收到错误<form action="example.php" method="POST">
<select name="test" id="test">
<?php
$dir="./files";
if (is_dir ($dir))
{
if ($dh = opendir($dir))
{
while (($file = readdir($dh)) != false)
{
if ($file != ".." && $file != "." && strtolower(substr($file,strrpos($file,'.') +1)) == 'txt)
{
echo "option value =\"$file\"> $file </option>";
}
}
}
}
?>
</select>
<input type="Submit" value="Ok">
</form>
。解决这个问题的最佳方法是什么?
答案 0 :(得分:0)
您收到的错误是由于未提供第二个参数next http.Handler
。
在如何使用中间件的情况下,我建议您查看http.ServeMux
https://golang.org/src/net/http/server.go?s=57308:57433#L1890的实现,它基本上会执行您尝试做的事情(然后是一些)虽然路由。因此,使用http.Handler结构可能比使用Handler函数更容易,这样您在函数中作为next http.Handler
参数的Handler只是结构中的一个字段。父处理程序可以在其ServeHTTP()
内进行调用。
总而言之,您可能希望使用实现http.Handler
接口的结构。这样它就可以拥有子处理程序和数据库访问权限。这样你也不必继续传递这个AppContext
。
答案 1 :(得分:-1)
我不会过早设置上下文。特别是请求作用域。
我宁愿创建一个小而专用的中间件,用于将数据库会话从池传递到上下文中,并检索在主处理程序中为请求创建的所述会话。
func DBSession(sess *mgo.Session, next http.Handler) http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// Create a new session for the scope of the request
s := sess.Copy()
// Make it close when exiting scope
defer s.Close()
// Add the new session (actually a pointer to it)
// acessible via the name "_sess"
ctx = context.WithValue(r.Context(), "_sess", s)
// execute the next handler
next(w, r.WithContext(ctx))
})
}
现在您可以在main.go中使用此中间件
package main
import (
"net/http"
"gopkg.in/mgo.v2"
)
func sayHello(w http.ResponseWriter, r *http.Request) http.Handler{
return http.HandlerFunc(
func (w http.ResponseWriter, r *http.Request) {
s := r.Context().Value("_sess").(*mgo.Session)
// Do something with your database here.
}
)
}
func main() {
// Ignoring err for brevity
sess, _ := mgo.Dial("localhost:27017")
// Magic happens here: the sayHello Handler is wrapped in the
// DBSession middleware, which makes the session available
// as context param _sess and closes the session after sayHello
// executed. No clutter in your controller for setting up and tearing down
// the session, no way you can forget to close it.
http.Handle("/", middleware.DBSession(sess, sayHello))
}