首页 > 解决方案 > 在 Go 中将任意函数作为参数传递

问题描述

我正在尝试扩展我对 Go 函数指针的了解,并且我有一个关于在 Go 中将函数作为参数传递的可能性和不可能的问题。

假设我想编写一个decorator()可以包装任何现有函数的函数。为简单起见,让我们将其限制为只接受一个参数并只返回一个值的函数。

如果我编写一个接受func(interface{}) interface{}作为参数的装饰器,只要我传入的函数也接受/返回一个interface{}类型,它就会隐式工作(请参阅 参考资料funcA)。

我的问题是——有没有办法将现有的类型函数转换为func(string) string类型,func(interface{}) interface{}以便它也可以传递给装饰器函数,而无需将其包装在新的匿名函数中(请参阅 参考资料funcB)?

package main

import (
    "fmt"
)

func decorate(inner func(interface{}) interface{}, args interface{}) interface {} {
    fmt.Println("Before inner")
    result := inner(args)
    fmt.Println("After inner")
    return result
}

func funcA(arg interface{}) interface{} {
    fmt.Print("Inside A, with arg: ")
    fmt.Println(arg)
    return "This is A's return value"
}

func funcB(arg string) string {
    fmt.Print("Inside B, with arg: ")
    fmt.Println(arg)
    return "This is B's return value"
}

func main() {
    
    // This one works. Output is:
    //
    //   Before inner
    //   Inside A, with arg: (This is A's argument)
    //   After inner
    //   This is A's return value
    //
    fmt.Println(decorate(funcA, "(This is A's argument)"))
    
    // This doesn't work. But can it?
    //fmt.Println(decorate(funcB, "(This is B's argument)"))
}

标签: godecoratorfunction-pointers

解决方案


这是不可能的。原因之一是传递参数的机制因函数而异,使用interface{}arg 并不意味着“接受任何东西”。例如,一个以结构为参数的函数将接收该结构的每个成员,但一个以 interface{} 包含该结构的函数将接收两个字,一个包含结构的类型,另一个包含指向它。

因此,在不使用泛型的情况下,实现这一点的唯一方法是使用适配器函数。


推荐阅读