英文:
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)
}
}
如你所见,中间件是一个函数,它:
- 接受一个
http.HandlerFunc
作为参数; - 返回一个
http.HandlerFunc
; - 调用传入的
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 (
"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"
// Run the next handler
next.ServeHTTP(w, r)
}
}
As you can see, a middleware is a function that:
- accepts a
http.HandlerFunc
as an argument; - returns a
http.HandlerFunc
; - calls the
http.handlerFunc
passed in.
With this basic technique you can "chain" as many middlewares as you like:
http.HandleFunc("/foo", 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论