为了账号安全,请及时绑定邮箱和手机立即绑定

恐慌:最后一个参数需要是 http.HandlerFunc 类型

恐慌:最后一个参数需要是 http.HandlerFunc 类型

Go
蓝山帝景 2023-05-22 15:36:47
我有这个辅助函数,可以正常编译:func Middleware(adapters ...interface{}) http.HandlerFunc {    log.Info("length of adapters:", len(adapters))    if len(adapters) < 1 {        panic("Adapters need to have length > 0.");    }    h, ok := (adapters[len(adapters)-1]).(http.HandlerFunc)    if ok == false {        panic("Last argument needs to be of type http.HandlerFunc") // ERROR HERE    }    adapters = adapters[:len(adapters)-1]    for _, adapt := range adapters {        h = (adapt.(AdapterFunc))(h)    }    return h}我这样称呼它:router.HandleFunc("/share", h.makeGetMany(v)).Methods("GET")func (h Handler) makeGetMany(v Injection) http.HandlerFunc {    return mw.Middleware(        mw.Allow("admin"),        func(w http.ResponseWriter, r *http.Request) {            log.Println("now we are sending response.");            json.NewEncoder(w).Encode(v.Share)        },    )}问题是我收到此错误,但我无法弄清楚原因:    panic: Last argument needs to be of type http.HandlerFunc    goroutine 1 [running]:    huru/mw.Middleware(0xc420083d40, 0x2, 0x2, 0xc42011f3c0)            /home/oleg/codes/huru/api/src/huru/mw/middleware.go:301 +0x187    huru/routes/share.Handler.makeGetMany(0xc4200ae1e0, 0x10)            /home/oleg/codes/huru/api/src/huru/routes/share/share.go:62 +0x108它确实确认适配器切片的长度为 2: length of adapters:2有谁知道为什么在这种情况下该类型断言会失败?没有意义。也许我实际上并没有检索切片的最后一个参数之类的?有没有更好的方法从切片中弹出最后一个参数?
查看完整描述

2 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

您需要使用 .将mw.Middleware()语句的第二个参数包装到类型中。http.Handlerhttp.HandlerFunc()


func (h Handler) makeGetMany(v Injection) http.HandlerFunc {

    return mw.Middleware(

        mw.Allow("admin"),

        http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

            log.Println("now we are sending response.");

            json.NewEncoder(w).Encode(v.Share)

        }),

    )

}


查看完整回答
反对 回复 2023-05-22
?
catspeake

TA贡献1111条经验 获得超0个赞

在 http 包中, ListenAndServe具有以下签名

func ListenAndServe(addr string, handler Handler) error

其中Handler(ie, http.Handler) 是一个接口

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

对于一个 Web 应用程序,只有一个ListenAndServe调用,因此只有一个handler,它需要处理所有访问点,例如/url1,/url2等。如果我们从头开始编写handler,实现可能是struct一个围绕数据库句柄的自定义。它的ServeHTTP方法是检查访问点,然后把相应的内容写入到ResponseWriter,比较繁琐和杂乱。

这就是ServeMux的动机,它router在您的代码中。它有一个ServeHTTP方法,因此它满足http.Handler接口并可用于ListenAndServe. 此外,它还有HandleFunc处理个别接入点的方法

func (mux *ServeMux) HandleFunc(pattern string,
                                handler func(ResponseWriter, *Request))

注意这里handler不是 a http.Handler,即它没有ServeHTTP方法。它不必这样做,因为它mux已经拥有ServeHTTP并且它的ServeHTTP方法可以将各个访问点请求分派给相应的处理程序。

请注意,它还有一个Handle方法,该方法需要参数满足http.Handler接口。与方法相比,使用起来稍微不方便HandleFunc

func (mux *ServeMux) Handle(pattern string, handler Handler)

现在回到你的问题,因为你打电话router.HandleFunc,它的输入不一定是http.Handler。因此,另一种解决方案是用作func(ResponseWriter, *Request)中间件和makeGetMany方法的返回类型。(中间件中的类型断言也需要更新,可能还需要更新更多代码)

@xpare 的解决方案是进行类型转换,以便所有函数签名匹配,即转换func(ResponseWriter, *Request)http.HandlerFunc. 看看它是如何工作的也很有趣。

// The HandlerFunc type is an adapter to allow the use of

// ordinary functions as HTTP handlers. If f is a function

// with the appropriate signature, HandlerFunc(f) is a

// Handler that calls f.

type HandlerFunc func(ResponseWriter, *Request)


// ServeHTTP calls f(w, r).

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {

    f(w, r)

}

你可以看到它基本上定义了一个ServeHTTP调用自身的方法。


查看完整回答
反对 回复 2023-05-22
  • 2 回答
  • 0 关注
  • 114 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信