HandlerFunc(f)如何将函数转换为接口类型?

When check following code, got a doubt with type convert from function to interface.


Code

http_hello.go:

package main

import (
    "fmt"
    "log"
    "net/http"
)

// hello http,
func helloHttp() {
    // register handler,
    http.Handle("/", http.HandlerFunc(helloHandler))

    // start server,
    err := http.ListenAndServe(":9090", nil)
    if err != nil {
        log.Fatal("ListenAndServe:", err)
    }

}

// handler function - hello,
func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, you've requested: %s
", r.URL.Path)
}

func main() {
    helloHttp()
}

The above code works.

(Then I tried to write a small program to check is this a general feature, but it won't work, check following code)

func_to_intf.go:

package main

import (
    "fmt"
)

// an interface,
type Adder interface {
    add(a, b int) int
}

// alias of a function signature,
type AdderFunc func(int, int) int

// a simple add function,
func simpleAdd(a, b int) int {
    return a + b
}

// call Adder interface to perform add,
func doAdd(a, b int, f Adder) int {
    return f.add(a, b)
}

func funcToIntf() {
    fa := AdderFunc(simpleAdd)
    fmt.Printf("%#v, type: %T
", fa, fa)

    a, b := 1, 2
    sum := doAdd(a, b, fa)
    fmt.Printf("%d + %d = %d
", a, b, sum)
}

func main() {
    funcToIntf()
}

Output:

./func_to_intf.go:30:14: cannot use fa (type AdderFunc) as type Adder in argument to doAdd: AdderFunc does not implement Adder (missing add method)


Questions

  1. http.HandlerFunc(helloHandler) get a value of type http.Handler, since that's what http.Handle() expect, is that correct?
  2. If yes, then means it convert a function into a value of an interface type, how did that happen?
    • Is this a built-in feature of go?
      I did a test (as in func_to_intf.go above), and seems not.
    • Or, is http.HandlerFunc's special implementation achieve that?

@Update - Summary

(Though the answer(s) addressed the questions pretty well, but after reviewing & more testing, there are several other go features required to totally erase the original doubt, as following.)

  • Function type.
    Function is value, and it has type.
    Function type could be defined via type keyword on a function signature.
    e.g type AdderFunc func(int, int) int
  • Type convertor T(v) on function.
    Any function could be converted to a function type with the same signature, just via T(v), use function type name as T, and actual function as v.
    Then when the new value is called, the actual function v is called.
    e.g fa := AdderFunc(simpleAdd)
    (this is blur to me before asking the question, and that's one of the main reason I was confused).

It is a simple type-conversion.

In Go you can define custom type besides structs. In this case, http.HandlerFunc is a function type, func(http.ResponseWriter,*http.Request). Since your function is of the same underlying type (signature) as the custom type, it can be converted to it.

Furthermore, code can define methods on custom type, no matter what underlying type it is, or whether it is a struct or not. In this case, http package defines ServeHTTP method on it, and of course, it just calls the function itself.

You can read the source code here: https://golang.org/src/net/http/server.go?s=58384:58444#L1936

As for the adder in your sample code, you can do the same: Define a method on AdderFunc.

func (a AdderFunc) add(x, y int) int {
    return a(x, y)
}

Playground: https://play.golang.org/p/5mf_afHLQA2

Not special or built-in feature. Instead http.HandlerFunc is a type that implements the http.Handler interface. Have a look at its implementation which is quite nifty https://github.com/golang/go/blob/d3c3aaa61f7598f275f30fabd3749379fe0f2720/src/net/http/server.go#L1956

As the docs say:

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.

So, it's not a function, but a wrapper type, declared as:

type HandlerFunc func(ResponseWriter, *Request)

But Go allows (and that's one of its greatest features, in my opinion) to make any newly declared type implement any possible interface just by defining the require method. So the type HandlerFunc implements the interface Handler by defining the method ServeHttp. The implementation just calls the wrapped function.

http.HandlerFunc is a type that satisfy interface http.Handler by providing method http.ServeHTTP(ResponseWriter, *Request).

http.HandlerFunc(helloHandler) is a type conversion which convert types with same underlying base type but different method set.

You example working