函数可以在Go中实现一个接口

时间:2017-11-27 11:01:06

标签: function go interface

我正在尝试创建一个类似于http.Handler的界面。对于我的API的某些端点,我需要查询中包含的APNS令牌,或者我需要使用http.StatusBadRequest进行回复。

我希望类型DeviceHandlerFunc能够实现ServeHTTP(http.ResponseWriter, *http.Request)并自动解析令牌并使用令牌调用自身:

type DeviceHandlerFunc func(http.ResponseWriter, *http.Request, string)

func (f DeviceHandlerFunc) ServeHTTP(res http.ResponseWriter, req *http.Request) {
    token := req.URL.Query().Get("token")

    if token == "" {
        http.Error(res, "token missing from query", http.StatusBadRequest)
    } else {
        f(res, req, token)
    }
}

然后从main.go

func main() {
    mux := http.NewServeMux()
    mux.Handle("/", getDevice)
    log.Fatal(http.ListenAndServe(":8081", mux))
}

func getDevice(res http.ResponseWriter, req *http.Request, token string) {
    // Do stuff with token...
}

这会导致编译错误:

main.go:22:13: cannot use getDevice (type func(http.ResponseWriter, *http.Request, string)) as type http.Handler in argument to mux.Handle:
    func(http.ResponseWriter, *http.Request, string) does not implement http.Handler (missing ServeHTTP method)

在我看来,我无法更清楚func(http.ResponseWriter, *http.Request, string)类型实现http.Handler。我做错了什么?

示例代码as playground

1 个答案:

答案 0 :(得分:3)

您的DeviceHandlerFunc类型确实实现了http.Handler。那不是问题。

但您的getDevice()函数 类型为DeviceHandlerFunc,它的类型为func(http.ResponseWriter, *http.Request, string)(这是一种未命名的类型,显然没有实现{{1} }})。

要使其有效,请使用简单类型conversion

http.Handler

您可以将mux.Handle("/", DeviceHandlerFunc(getDevice)) 转换为getDevice,因为DeviceHandlerFunc的基础类型与DeviceHandlerFunc的类型相同。在Go Playground上尝试。

以下内容也适用:

getDevice

此处var f DeviceHandlerFunc = getDevice mux.Handle("/", f) 的类型显然是f。您可以将DeviceHandlerFunc分配给getDevice,因为assignability规则适用,即此规则:

  

[值f可分配给x类型的变量(“T可分配给x”)在以下任何情况下:]

     
      
  • T的类型xV具有相同的基础类型,TV中至少有一个不是已定义的类型。
  •