go - 如何使用反射从另一个函数创建新函数

标签 go go-reflect

使用此代码作为模板

package main

import "fmt"

type myStruct struct {
    Value int
}

type counter int

func newFuncHandler(fn func(myStruct) error) (interface{}, *counter) {
    count := counter(0)

    newFn := func(e myStruct) error {
        count = count + 1
        return fn(e)
    }

    return newFn, &count
}

func main() {
    fn := func(d myStruct) error {
        // doing some stuff
        return nil
    }

    handle, c := newFuncHandler(fn)
    handleFn := handle.(func(d myStruct) error)

    handleFn(myStruct{Value: 2})
    handleFn(myStruct{Value: 2})
    handleFn(myStruct{Value: 2})
    handleFn(myStruct{Value: 2})
    handleFn(myStruct{Value: 2})

    fmt.Println(*c) // 5
}


如何修改newFuncHandler,以使其在给定具有未知签名的函数的情况下返回具有相同签名但为函数主体提供附加代码的函数。 newFuncHandler不应该知道myStruct类型

例如

func newFuncHandler(fn interface{}) (interface{}, *counter) {
    count := counter(0)
    // some reflection magic

    // newFn has the same signature as fn (hardcoded in this case)
    newFn := func(e myStruct) error {
        // add custom code 
        count = count + 1

        // call the original fn
        return fn(e)
    }

    return newFn, &count
}

最佳答案

使用reflect.MakeFunc进行功能。使用Value.Call调用函数。

func newFuncHandler(v interface{}) (interface{}, *counter) {
    count := counter(0)
    fn := reflect.ValueOf(v)
    newFn := reflect.MakeFunc(fn.Type(), func(args []reflect.Value) (results []reflect.Value) {
        count = count + 1
        return fn.Call(args)
    })
    return newFn.Interface(), &count
}

Run it on the playground

关于go - 如何使用反射从另一个函数创建新函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61001554/

相关文章:

go - 类型转换接口(interface) slice

swift - 将 json 编码时间转换为 nsdate

Golang : implements http server health checking. gocraft/health

go - 无锁并发访问变量

go - 检查方法类型是否与函数类型匹配

go - 传入 Reflect.New(Type) 的结果时,v.Elem() 与 Indirect(v)

go - 从 Golang 中的函数列表中选择一个函数

unit-testing - Golang单元测试: error conditions

shell - 如何在 Go 中执行具有多个 iname 匹配器的查找命令?

go - 遍历 Go 中结构的字段