dongshang6062 2017-09-10 19:16
浏览 81
已采纳

Go中的函数类型-将特定类型转换为更通用的类型

What cast / assertion need I do in Go in order to pass to a function expecting a generic function like func(interface{}) interface{}, a more specific function like func(int) int instead?

For example, in code like this, fooA can be passed to MakeExclamer, but not fooB:

func MakeExclamer(foo func (interface{}) interface{}, n int) func () {
    return func() {
        fmt.Printf("%v!!!", foo(n))
    }
}

func fooA(x interface{}) interface{} {
    return x.(int)*2
}

func fooB(x int) int {
    return x * 10
}

func main() {
    exclamerA := MakeExclamer(fooA, 12)
    exclamerA()
    exclamerB := MakeExclamer(fooB, 66)
// >> cannot use fooB (type func(int) int) as type func(interface {}) interface {} in argument to MakeExclamer 
    exclamerB()
}

(Go Playground link: https://play.golang.org/p/xGzfco0IAG)

I'm not interested much in alternative code structure patterns, since this is how I want it to work: a specific function should be passed to a general function transformer (accepting function of type Any -> Any) that will return another general function (Any -> Any). This may not be idiomatic in Go, but it is the pattern that I want my code to follow.

  • 写回答

2条回答 默认 最新

  • douchi2022 2017-09-10 21:37
    关注

    To use type assertions, every possible type must be enumerated in MakeExclamer:

    func MakeExclamer(fn interface{}, arg interface{}) func() {
        switch fn := fn.(type) {
        case func(int) int:
            return func() {
                fmt.Printf("%v!!!
    ", fn(arg.(int)))
            }
        case func(interface{}) interface{}:
            return func() {
                fmt.Printf("%v!!!
    ", fn(arg))
            }
        default:
            panic("not supported")
        }
    }
    

    To accept a function of any type, the fn argument is declared as type interface{}. The code uses a type switch to handle the different function types.

    playground example

    Reflection can be used to write a more general function.

    func MakeExclamer(fn interface{}, arg interface{}) func() {
        fnr := reflect.ValueOf(fn)
        argr := reflect.ValueOf(arg)
        return func() {
            resultr := fnr.Call([]reflect.Value{argr})
            fmt.Printf("%v!!!
    ", resultr[0].Interface())
        }
    }
    

    playground example

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

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料