Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function GO中的函数包装器_Function_Go_Wrapper - Fatal编程技术网

Function GO中的函数包装器

Function GO中的函数包装器,function,go,wrapper,Function,Go,Wrapper,我需要一个函数包装器,它将接受一个函数并返回它的包装器版本。我试图实现的是在函数执行之前和之后注入一些代码 func funcWrapper(myFunc interface{}){ fmt.Println("Before") //call myFunc fmt.Println("After") } 如果知道函数的签名,可以创建一个函数,该函数接受该函数类型的函数值,并返回另一个相同类型的函数值。您可以使用执行要添加到其中的额外功能的,并在适当时调用传递的函数 例如,假

我需要一个函数包装器,它将接受一个函数并返回它的包装器版本。我试图实现的是在函数执行之前和之后注入一些代码

func funcWrapper(myFunc interface{}){
    fmt.Println("Before")
    //call myFunc
    fmt.Println("After")
}

如果知道函数的签名,可以创建一个函数,该函数接受该函数类型的函数值,并返回另一个相同类型的函数值。您可以使用执行要添加到其中的额外功能的,并在适当时调用传递的函数

例如,假设我们有这个函数:

func myfunc(i int) int {
    fmt.Println("myfunc called with", i)
    return i * 2
}
func wrap(f interface{}) interface{} {
    switch f2 := f.(type) {
    case func(i int) (ret int):
        return func(i int) (ret int) {
            fmt.Println("Before func(i int) (ret int), i =", i)
            ret = f2(i)
            fmt.Println("After func(i int) (ret int), ret =", ret)
            return
        }
    case func():
        return func() {
            fmt.Println("Before func()")
            f2()
            fmt.Println("After func()")
        }
    }
    return nil
}
一种函数,它接受一个
int
,并返回一个
int
(输入数的两倍)

这里有一个可能的包装器,它在调用之前和之后通过日志记录对其进行“注释”,还记录其输入和返回值:

func wrap(f func(i int) int) func(i int) int {
    return func(i int) (ret int) {
        fmt.Println("Before, i =", i)
        ret = f(i)
        fmt.Println("After, ret =", ret)
        return
    }
}
测试它的示例:

wf := wrap(myfunc)
ret := wf(2)
fmt.Println("Returned:", ret)
wf := wrap(myfunc).(func(int) int)
ret := wf(2)
fmt.Println("Returned:", ret)

wf2 := wrap(myfunc2).(func())
wf2()
输出(在上尝试):

由于Go不支持泛型,因此必须为要支持的每个不同的函数类型执行此操作。或者你可以试着写一个通用的解决方案,正如你在这个问题中看到的:,使用它会很痛苦

如果您想支持多个函数类型,最好为每个不同的函数类型创建一个单独的包装器,这样每个函数类型都可以有适当的返回类型(具有适当参数和结果类型的函数类型)。如果您还希望支持不带参数和返回类型的包装函数,则可能会出现这种情况:

func wrap(f func()) func() {
    return func() {
        fmt.Println("Before func()")
        f2()
        fmt.Println("After func()")
    }
}

func wrapInt2Int(f func(i int) int) func(i int) int {
    return func(i int) (ret int) {
        fmt.Println("Before func(i int) (ret int), i =", i)
        ret = f(i)
        fmt.Println("After func(i int) (ret int), ret =", ret)
        return
    }
}
func myfunc2() {
    fmt.Println("myfunc2 called")
}
您可以在下面这样的单个
wrap()
函数中实现它,但它的缺点(类型安全性较低,更难使用)超过了它的优点,因此我建议不要这样做,我只需要为不同的函数类型创建单独的包装函数

我们还支持包装没有参数和返回类型的函数:

func wrap(f func()) func() {
    return func() {
        fmt.Println("Before func()")
        f2()
        fmt.Println("After func()")
    }
}

func wrapInt2Int(f func(i int) int) func(i int) int {
    return func(i int) (ret int) {
        fmt.Println("Before func(i int) (ret int), i =", i)
        ret = f(i)
        fmt.Println("After func(i int) (ret int), ret =", ret)
        return
    }
}
func myfunc2() {
    fmt.Println("myfunc2 called")
}
包装器函数:

func myfunc(i int) int {
    fmt.Println("myfunc called with", i)
    return i * 2
}
func wrap(f interface{}) interface{} {
    switch f2 := f.(type) {
    case func(i int) (ret int):
        return func(i int) (ret int) {
            fmt.Println("Before func(i int) (ret int), i =", i)
            ret = f2(i)
            fmt.Println("After func(i int) (ret int), ret =", ret)
            return
        }
    case func():
        return func() {
            fmt.Println("Before func()")
            f2()
            fmt.Println("After func()")
        }
    }
    return nil
}
测试它:

wf := wrap(myfunc)
ret := wf(2)
fmt.Println("Returned:", ret)
wf := wrap(myfunc).(func(int) int)
ret := wf(2)
fmt.Println("Returned:", ret)

wf2 := wrap(myfunc2).(func())
wf2()
输出(在上尝试此选项):


由于Go中没有泛型,此解决方案只能有一个返回类型
接口{}
,使用它时,必须手动将其返回值“转换”为您希望它返回的函数类型(例如
wf2:=wrap(myfunc2)。(func()
)。

这里有一种方法


包干管
进口(
“fmt”
)
func跟踪(funcName字符串)func(){
fmt.Println(“pre”,funcName)
返回func(){
fmt.Println(“post”,funcName)
}
}
func doSomething(名称字符串){
延迟跟踪(“某物”)()
fmt.Println(名称)
}
func main(){
剂量测定法(“试验”)
}

写了一个答案,然后意识到这并不是你所问的。你有没有试过看看他们是怎么做到的:?如果签名是已知的,像这样的东西可能会有所帮助:签名是已知的,但它是不同的,大约有10种类型的签名,我需要手工编写一些类似闭包的东西来包装你的函数。