Go: How to use middleware pattern?

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

Go: How to use middleware pattern?

问题

我有一个只在特定条件下执行的函数(例如,role == 'Administrator')。现在,我使用if语句来实现。但是当条件数量很多时,使用长定义的if语句看起来不太美观。

在Go语言(或与Go相关的框架)中是否有一种机制可以实现中间件概念(动作过滤器)?

例如,ASP.NET MVC允许这样做:

[MyFilter]
public ViewResult Index()
{
// 这个特定的动作方法将应用过滤器
}

因此,将MyFilter()实现在单独的类中可以更好地组织和测试代码。

更新:
Revel(Go语言的Web框架)提供了类似的功能,使用拦截器(在调用动作之前或之后由框架调用的函数):https://revel.github.io/manual/interceptors.html

英文:

I have a function that executes only with specific conditions (e.g. <i>role == 'Administrator'</i>). Now, I use <i>'if'</i> statement. But it could be situations when number of conditions is high and <i>'if'</i> with long definition looks not so esthetic.<br>
Is it available mechanism in Go (or related with Go framework) allows implementation of middleware <b>concept</b> (action filters)?<br><br>
<i>For example, ASP.NET MVC allows to do this:</i>

[MyFilter]
public ViewResult Index()
{
     // Filter will be applied to this specific action method
}

<i>So, MyFilter() implemented in the separate class allows better code composition and testing.</i><br>

<b>Update:</b>
Revel (web framework for the Go) provides similar functionality with
Interceptors (function that is invoked by the framework BEFORE or AFTER an action invocation): https://revel.github.io/manual/interceptors.html

答案1

得分: 5

这种类型的事情通常在Go语言中使用中间件来完成。最简单的方法是通过示例来展示:

package main

import (
    "fmt"
    "html"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/foo", middleware(handler))

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}

func middleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        r.URL.Path = "/MODIFIED"

        // 运行下一个处理程序
        next.ServeHTTP(w, r)
    }
}

如你所见,中间件是一个函数,它:

  1. 接受一个http.HandlerFunc作为参数;
  2. 返回一个http.HandlerFunc
  3. 调用传入的http.HandlerFunc

使用这种基本技术,你可以“链式”地连接任意多个中间件:

http.HandleFunc("/foo", another(middleware(handler)))

这种模式有一些变体,大多数Go框架使用稍微不同的语法,但概念通常是相同的。

英文:

This sort of thing is typically done with middleware in Go. The easiest is to show by example:

package main

import (
    &quot;fmt&quot;
    &quot;html&quot;
    &quot;log&quot;
    &quot;net/http&quot;
)

func main() {
    http.HandleFunc(&quot;/&quot;, handler)
    http.HandleFunc(&quot;/foo&quot;, middleware(handler))

    log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, &quot;Hello, %q&quot;, html.EscapeString(r.URL.Path))
}

func middleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        r.URL.Path = &quot;/MODIFIED&quot;

        // Run the next handler
        next.ServeHTTP(w, r)
    }
}

As you can see, a middleware is a function that:

  1. accepts a http.HandlerFunc as an argument;
  2. returns a http.HandlerFunc;
  3. calls the http.handlerFunc passed in.

With this basic technique you can "chain" as many middlewares as you like:

http.HandleFunc(&quot;/foo&quot;, another(middleware(handler)))

There are some variants to this pattern, and most Go frameworks use a slightly different syntax, but the concept is typically the same.

答案2

得分: 0

Revel(用于Go的Web框架)提供了类似的功能,使用拦截器(在操作调用之前或之后由框架调用的函数)实现。有关概念和实现的描述,请参考这里:https://revel.github.io/manual/interceptors.html

英文:

Revel (web framework for the Go) provides similar functionality with<br>
<b>Interceptors</b> (function that is invoked by the framework BEFORE or AFTER an action invocation).<br>
Concept and implementation described here: https://revel.github.io/manual/interceptors.html

huangapple
  • 本文由 发表于 2016年11月17日 06:42:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/40643671.html
匿名

发表评论

匿名网友

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

确定