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 Java-Oj-桌布的计算
  • ¥15 请问如何在openpcdet上对KITTI数据集的测试集进行结果评估?
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗
  • ¥15 ikuai客户端l2tp协议链接报终止15信号和无法将p.p.p6转换为我的l2tp线路