Golang闭包代码解析 - 书中讲解不够清晰求解答
Golang闭包代码解析 - 书中讲解不够清晰求解答
package main
import (
"fmt"
"net/http"
)
func testHandlerFunc(w http.ResponseWriter, r *http.Request) {
fmt.Println("Printing from testHandlerFunc")
w.Write([]byte("From testHandlerFunc\n"))
}
func middleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Executing before request phase")
testHandlerFunc(w, r) // 这是在做什么?
handler.ServeHTTP(w, r)
fmt.Println("Executing after response phase")
})
}
func mainLogic(w http.ResponseWriter, r *http.Request) {
fmt.Println("Executing mainLogic")
w.Write([]byte("OK"))
}
func main() {
mainLogicHandler := http.HandlerFunc(mainLogic) // 我不完全理解为什么要把"mainLogic"放入http.HandlerFunc()类型中
http.Handle("/", middleware(mainLogicHandler)) // 这个我理解
}
这段代码可以运行,我理解使用闭包的意义。你可以使用函数将不同的代码片段链接在一起。我大概明白发生了什么,但书中的解释不是很清楚。我知道这是一个非常开放性的问题,我只是想彻底理解这个概念。
更多关于Golang闭包代码解析 - 书中讲解不够清晰求解答的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
package main
import (
"fmt"
"net/http"
)
func testHandlerFunc(w http.ResponseWriter, r *http.Request) {
fmt.Println("Printing from testHandlerFunc")
w.Write([]byte("From testHandlerFunc\n"))
}
func middleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Executing before request phase")
testHandlerFunc(w, r) // 这是在做什么?
// 这是用当前函数作用域的 http.ResponseWriter 和 http.Request
// 调用上面定义的 testHandlerFunc,即此处理器的参数
handler.ServeHTTP(w, r)
fmt.Println("Executing after response phase")
})
}
func mainLogic(w http.ResponseWriter, r *http.Request) {
fmt.Println("Executing mainLogic")
w.Write([]byte("OK"))
}
func main() {
mainLogicHandler := http.HandlerFunc(mainLogic) // 我不完全理解为什么要把 "mainLogic" 放入 http.HandlerFunc() 类型
// 这不是类型,而是一个返回 HandlerFunc 的函数调用,它为你基本的接口定义函数
// 提供了实际成为 HandlerFunc 所需的额外方法,例如 ServeHTTP
http.Handle("/", middleware(mainLogicHandler)) // 我理解这部分
}
更多关于Golang闭包代码解析 - 书中讲解不够清晰求解答的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个典型的Go语言中间件模式实现,通过闭包来包装HTTP处理器。让我详细解析代码中的关键部分:
闭包中间件解析
func middleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Executing before request phase")
testHandlerFunc(w, r) // 这里直接调用testHandlerFunc
handler.ServeHTTP(w, r) // 执行被包装的处理器
fmt.Println("Executing after response phase")
})
}
关键点解释:
-
testHandlerFunc(w, r)的作用:- 这行代码在中间件中直接调用另一个处理器函数
- 它会先执行
testHandlerFunc的逻辑,然后才执行原始的mainLogic - 实际上这会破坏正常的请求处理流程,因为两个处理器都会尝试写入响应
-
正确的中间件模式:
func properMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Executing before request phase")
// 这里应该只做预处理,比如认证、日志等
// 不应该直接调用其他处理器
handler.ServeHTTP(w, r) // 继续执行链中的下一个处理器
fmt.Println("Executing after response phase")
})
}
http.HandlerFunc类型转换解析
mainLogicHandler := http.HandlerFunc(mainLogic)
为什么需要这个转换:
- 类型系统要求:
http.Handle函数需要http.Handler接口类型 - 适配器模式:
http.HandlerFunc是一个函数类型,它实现了http.Handler接口
// 在net/http包中的定义:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r) // 这里调用原始函数
}
实际执行流程:
- 请求到达
/路径 - 调用
middleware(mainLogicHandler) - 中间件闭包执行前置逻辑
- 调用
handler.ServeHTTP(w, r)即mainLogicHandler.ServeHTTP(w, r) mainLogicHandler.ServeHTTP调用mainLogic(w, r)- 中间件闭包执行后置逻辑
完整的工作示例
func loggingMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
fmt.Printf("Started %s %s\n", r.Method, r.URL.Path)
handler.ServeHTTP(w, r)
fmt.Printf("Completed %s in %v\n", r.URL.Path, time.Since(start))
})
}
func authMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token != "valid-token" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
handler.ServeHTTP(w, r)
})
}
func main() {
mainHandler := http.HandlerFunc(mainLogic)
// 中间件链:logging -> auth -> mainLogic
chain := loggingMiddleware(authMiddleware(mainHandler))
http.Handle("/", chain)
http.ListenAndServe(":8080", nil)
}
这种闭包模式允许你在不修改原始处理器的情况下,为HTTP请求处理添加额外的功能层。

