我正在尝试编写一个Web应用程序,并努力编写干净的代码。
我有一个控制器来处理传入请求和基本控制器,所有控制器都会借用这些字段。
这是我的基本控制器
type Controller struct {
Request *http.Request
Response http.ResponseWriter
// Reqeust language
lang string
// HTML parts
Title string
body string
head string
content string
view string
errors []string
success []string
}
// And methods followed here
func (self *Controller) renderHeadView() { .....
和我的注册控制器
type Controller struct {
base.Controller
user *account
}
func (self *Controller) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
self.Title = "Sign Up"
self.Request = r
self.Response = rw
self.lang = header.Language(self.Request)
self.user = &account{lang: self.lang}
switch self.Request.Method {
case "GET":
self.get()
case "POST":
if err := self.post(); err != nil {
self.get()
} else {
// If everything was successfully
return
}
}
self.RenderResponseView()
}
和我的激活控制器
type Controller struct {
base.Controller
}
func (self *Controller) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
self.Title = "Activate account"
self.Request = r
self.Response = rw
self.lang = header.Language(self.Request)
self.RenderResponseView()
}
如您所见,ServeHTTP方法看起来几乎相同。我正在考虑将ServeHTTP移动到基本控制器中,然后提供一种方法来调用特殊工作。为了澄清我的意思,请看下面的代码片段(基本控制器)
func (self *Controller) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
self.Title = "Activate account"
self.Request = r
self.Response = rw
self.lang = header.Language(self.Request)
// here would come function for special work
function()
self.RenderResponseView()
}
我不知道如何提供此实现。如果有人能给我一些建议,我会很高兴的。
答案 0 :(得分:5)
要引用的好文章是“Middlewares in Go: Best practices and examples”
在Go中编写Web应用程序时遇到的第一个代码异味是代码重复 在处理请求之前,我们经常需要记录请求,将应用程序错误转换为HTTP 500错误,对用户进行身份验证等。我们需要为每个处理程序执行大部分操作。
我们可以创建一个带闭包的函数。但是如果我们有这样的多个函数,它将变得像Javascript中的回调意大利面一样糟糕。我们不希望这样。
因此我们可以编写一个处理程序并将另一个处理程序传递给它。
loggingHandler(recoverHandler(indexHandler))
所以中间件就像
进行调用func (http.Handler) http.Handler
一样 这样我们传递一个处理程序并返回一个处理程序。最后我们有一个处理程序,可以使用http.Handle(pattern, handler)
Alice is a small package to chain handlers more elegantly。此外,我们可以创建一个公共的处理程序列表,并为每条路径重用它们,如下所示:
func main() {
commonHandlers := alice.New(loggingHandler, recoverHandler)
http.Handle("/about", commonHandlers.ThenFunc(aboutHandler))
http.Handle("/", alice.New(commonHandlers, bodyParserHandler).ThenFunc(indexHandler))
http.ListenAndServe(":8080", nil)
}
问题解决了。我们现在有一个惯用的中间件系统,并使用标准接口。 Alice是50行代码,所以它是一个非常小的依赖。