Shawn Throop
Shawn Throop

Reputation: 1291

Can functions implement an interface in Go

I'm trying to make an interface similar to http.Handler. For certain endpoints of my API I need a APNS token included in the query or I need to respond with http.StatusBadRequest.

I want the type DeviceHandlerFunc to implement ServeHTTP(http.ResponseWriter, *http.Request) and automatically parse the token and call itself with the token:

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)
    }
}

Then from 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...
}

This causes a compiler error:

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)

In my mind I couldn't be more clear that the type func(http.ResponseWriter, *http.Request, string) implements http.Handler. What am I doing wrong?

Sample code as playground.

Upvotes: 1

Views: 129

Answers (1)

icza
icza

Reputation: 417472

Your DeviceHandlerFunc type indeed implements http.Handler. That's not the problem.

But your getDevice() function is not of type DeviceHandlerFunc, it's of type func(http.ResponseWriter, *http.Request, string) (which is an unnamed type which obviously does not implement http.Handler).

To make it work, use a simple type conversion:

mux.Handle("/", DeviceHandlerFunc(getDevice))

You can convert getDevice to DeviceHandlerFunc as the underlying type of DeviceHandlerFunc is the same as the type of getDevice. Try it on the Go Playground.

The following would also work:

var f DeviceHandlerFunc = getDevice
mux.Handle("/", f)

Here type of f is obviously DeviceHandlerFunc. And you can assign getDevice to f as assignability rules apply, namely this one:

[A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:]

  • x's type V and T have identical underlying types and at least one of V or T is not a defined type.

Upvotes: 3

Related Questions