Go 如何编写一个函数代理,它接受一个转换为func(…x)…y的接口{},将结果绑定到一个指针值?

Go 如何编写一个函数代理,它接受一个转换为func(…x)…y的接口{},将结果绑定到一个指针值?,go,Go,我试图创建一个函数,它充当执行函数的代理 它接受一个指向将在其中设置结果的值的指针、一个func和多个参数。它执行函数并将结果应用于值 我的第一个挑战是执行函数,因为声明的类型不是func,也不能是func。我想我可以使用reflect.MakeFunc实现这一点,但我没有成功 下面是我试图实现的一个例子 package main import "fmt" // Execute the function which returns this struct type item struct {

我试图创建一个函数,它充当执行函数的代理

它接受一个指向将在其中设置结果的值的指针、一个func和多个参数。它执行函数并将结果应用于值

我的第一个挑战是执行函数,因为声明的类型不是func,也不能是func。我想我可以使用reflect.MakeFunc实现这一点,但我没有成功

下面是我试图实现的一个例子

package main

import "fmt"

// Execute the function which returns this struct
type item struct {
    key        string
    value      string
    otherValue string
}

func todo(param string) (*item, error) {
    return &item{
        key: param,
    }, nil
}

type BindFunc struct {
    Params  func(params ...interface{}) *BindFunc
    Results func(results ...interface{}) *BindFunc
    Do      func()
}

// NewBindFunc is a proxy function should run the function and bind the results
// to the result
func NewBindFunc(fn interface{}) *BindFunc {
    b := &BindFunc{}

    b.Params = func(params ...interface{}) *BindFunc {
        return b
    }

    b.Results = func(results ...interface{}) *BindFunc {
        return b
    }

    b.Do = func() {
        // execute the function
    }

    return b
}

func main() {
    var result item
    var err error

    NewBindFunc(todo).
        Params("Param").
        Results(&result, &err).
        Do()

    fmt.Println(result.key)
}
用于调用函数。通过使用BindFunc上的方法而不是带有函数的字段来简化代码

type BindFunc struct {
    params  []interface{}
    results []interface{}
    fn      interface{}
}

func (bf *BindFunc) Params(params ...interface{}) *BindFunc {
    bf.params = params
    return bf
}

func (bf *BindFunc) Results(results ...interface{}) *BindFunc {
    bf.results = results
    return bf
}

func (bf *BindFunc) Do() {
    // Copy params to slice of reflect values.
    var params []reflect.Value
    for _, p := range bf.params {
        params = append(params, reflect.ValueOf(p))
    }

    // Invoke the function.
    results := reflect.ValueOf(bf.fn).Call(params)

    // Copy the results.
    for i, r := range results {
        reflect.ValueOf(bf.results[i]).Elem().Set(r)
    }
}

// NewBindFunc is a proxy function should run the function and bind the results
// to the result
func NewBindFunc(fn interface{}) *BindFunc {
    return &BindFunc{fn: fn}
}
可以这样称呼:

var result *item
var err error

NewBindFunc(todo).
    Params("Param").
    Results(&result, &err).
    Do()

如果类型不匹配、参数数量不匹配或返回值数量不匹配,上述代码将死机。通过使用reflect包检查类型可以避免这种恐慌,但我将把它作为练习

我不知道完整的场景是什么,但可以用参数和结果的闭包来代替所有这些:

var result *item
var err error
do := func() { result, err = todo("Param") }
do()

非常感谢你的回答。通过阅读您的代码,我学到了很多。