Go语言实现类http.HandlerFunc中间件出现'used as value'编译错误
Go 自定义函数中间件仿 http.HandlerFunc 模式的编译报错问题
标准库参考逻辑
net/http 包的通用中间件模式核心是基于自定义函数类型实现的,对应的类型定义如下:
type HandlerFunc func(ResponseWriter, *Request)
类型说明:
HandlerFunc是一个适配器,允许普通函数直接作为HTTP处理器使用。只要函数签名匹配,HandlerFunc(f)就可以作为处理器被调用。
基于这个类型实现的中间件示例可以正常运行:
func middleware(fn http.HandlerFunc) http.HandlerFunc { return func (wr http.ResponseWriter, r *http.Request) { fmt.Println("doing something before") fn(wr, r) } } func main() { middleware(func (wr http.ResponseWriter, r *http.Request) { wr.Write([]byte("...")) }) }
自定义实现的编译报错根源
自行仿照实现时抛出 myFunc(3) used as value 编译错误,核心原因不在类型定义和标准库不一致,而是传参时错误地执行了函数,而非传递函数本身:
错误代码片段:
type FN func (arg int) func myFunc(arg int) { fmt.Println("Arg:",arg) } func do(fn FN) FN { return func (arg int) { fn(arg) } } func main() { do(myFunc(3)) // 报错行 }
具体差异拆解:
- 标准库示例中传给中间件的是匿名函数的定义本身,传参阶段没有触发函数执行,完全匹配
HandlerFunc类型的入参要求。 - 错误代码中
myFunc(3)是带调用括号的执行表达式,逻辑是立刻运行myFunc、传入参数3,等待函数执行完成后,把它的返回值作为入参传给do。但myFunc本身没有任何返回值,不存在可传递的值,因此编译器直接抛出报错。 - 哪怕给
myFunc加上返回值让代码能编译通过,逻辑也完全偏离中间件的设计:相当于先执行一次原始函数,再把返回值(比如整数0)传给do,并不是把原始函数作为处理逻辑包装进中间件。
正确的中间件调用方式
调整传参逻辑,传递函数本身而非函数执行结果,就可以实现和标准库完全一致的中间件效果:
package main import "fmt" type FN func (arg int) func do(fn FN) FN { return func (arg int) { fmt.Println("executed do with arg",arg) // 中间件附加逻辑 fn(arg) // 调用被包装的原始函数 } } func something(arg int){ fmt.Println("Executed something with arg",arg) } func main() { do(something)(3) // 第一步:传something函数本身给do,拿到包装后的函数;第二步:调用包装函数并传参3 }
运行输出:
executed do with arg 3 Executed something with arg 3 Program exited.
内容的提问来源于stack exchange,提问作者Mihai
相关产品推荐
相关产品推荐

