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\n", 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\n", fa, fa)
a, b := 1, 2
sum := doAdd(a, b, fa)
fmt.Printf("%d + %d = %d\n", 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
http.HandlerFunc(helloHandler)
get a value of typehttp.Handler
, since that's whathttp.Handle()
expect, is that correct?- 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 infunc_to_intf.go
above), and seems not. - Or, is
http.HandlerFunc
's special implementation achieve that?
- Is this a built-in feature of go?
@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 viatype
keyword on a function signature.
e.gtype 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 viaT(v)
, use function type name asT
, and actual function asv
.
Then when the new value is called, the actual functionv
is called.
e.gfa := AdderFunc(simpleAdd)
(this is blur to me before asking the question, and that's one of the main reason I was confused).
Answer
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
No comments:
Post a Comment