duanhegn231318 2018-08-05 11:56
浏览 59
已采纳

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).
  • 写回答

4条回答 默认 最新

  • dtd5644 2018-08-05 12:06
    关注

    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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 关于#java#的问题,请各位专家解答!
  • ¥15 急matlab编程仿真二阶震荡系统
  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?
  • ¥30 求解达问题(有红包)
  • ¥15 请解包一个pak文件