将httprouter包装为具有日志记录功能的方法?

huangapple go评论75阅读模式
英文:

Go wrap httprouter to have logger?

问题

我有以下的httprouter处理程序,但我想自定义它,以便我可以注入自己的日志记录函数。

router := httprouter.New()
router.Handle("GET", "/mysite", mylogger(handler1))

mylogger函数如下:

var logger = log.New(os.Stdout, "[Log] ", 0)
func mylogger(fn func(w http.ResponseWriter, r *http.Request, param httprouter.Params)) func(w http.ResponseWriter, r *http.Request, param httprouter.Params) {
    return func(w http.ResponseWriter, r *http.Request, param httprouter.Params) {
        start := time.Now()
        logger.Printf("%s %s", r.Method, r.URL.Path)
        fn(w, r, param)
        logger.Printf("Done in %v (%s %s)", time.Since(start), r.Method, r.URL.Path)
    }
}

myhandler函数如下:

func myhandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    ....
}

有没有办法可以包装httprouter处理程序,而不必将处理程序传递给mylogger函数?我想在Go AppEngine Context中做类似的事情:

func AppEngineHandler(c appengine.Context, w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  ...
  c.Infof("Here's my log")
}
英文:

I have the following httprouter handler but I want to customize so that I can inject my own logger functions.

router := httprouter.New()
router.Handle("GET", "/mysite", mylogger(handler1))

And mylogger is like:

var logger = log.New(os.Stdout, "[Log] ", 0)
func mylogger(fn func(w http.ResponseWriter, r *http.Request, param httprouter.Params)) func(w http.ResponseWriter, r *http.Request, param httprouter.Params) {
    return func(w http.ResponseWriter, r *http.Request, param httprouter.Params) {
	    start := time.Now()
	    logger.Printf("%s %s", r.Method, r.URL.Path)
	    fn(w, r, param)
	    logger.Printf("Done in %v (%s %s)", time.Since(start), r.Method, r.URL.Path)
    }
}

And myhandler is like:

func myhandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    ....
}

Is there any way that I can wrap the httprouter handler that I do not have to pass handler to mylogger function? I want to do something like in Go AppEngine Context:

func AppEngineHandler(c appengine.Context, w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  ...
  c.Infof("Here's my log")
}

答案1

得分: 0

没有使用过httprouter包之前,似乎你只需要改变你尝试包装的函数签名。

首先,在方法中改变fn参数的声明:

func mylogger(fn func(c *myapp.Context, w http.ResponseWriter, r *http.Request, param httprouter.Params))
//                    ^^^^^ 让它接受你自己的上下文

然后,在包装器中创建并传递上下文到处理程序中:

c := &myapp.Context{ your: arguments, here: true }
fn(c, w, r, param)
// ^^ - 传递上下文

接下来,改变处理程序的签名:

func myhandler(c *myapp.Context, w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    // 在这里使用 c
}

请注意,这只是根据你提供的代码片段进行的翻译,可能需要根据你的实际代码进行适当的调整。

英文:

Without having used the httprouter package before, it would appear all you need to do is change the function signature you're attempting to wrap.

So, firstly, change the declaration of the fn argument in the method:

func mylogger(fn func(c *myapp.Context, w http.ResponseWriter, r *http.Request, param httprouter.Params))
//                    ^^^^^ have it accept a context of your own

..then create and pass the context into your handler in the wrapper:

c := &myapp.Context{ your: arguments, here: true }
fn(c, w, r, param)
// ^^ - pass the context in

Then change the signature of your handler:

func myhandler(c *myapp.Context, w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    // use c here
}

huangapple
  • 本文由 发表于 2014年11月2日 09:20:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/26695062.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定