When check following code, got a doubt with type convert from function to interface.
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)
http.HandlerFunc(helloHandler)
get a value of type http.Handler
, since that's what http.Handle()
expect, is that correct?func_to_intf.go
above), and seems not.http.HandlerFunc
's special implementation achieve that?(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.)
type
keyword on a function signature.type AdderFunc func(int, int) int
T(v)
on function.T(v)
, use function type name as T
, and actual function as v
.v
is called.fa := AdderFunc(simpleAdd)
It is a simple type-conversion.
In Go you can define custom type besides struct
s. 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