gpt4 book ai didi

go - 我如何编写一个函数代理,它采用一个转换为 func(...x) ...y 的接口(interface){},并将结果绑定(bind)到一个指针值?

转载 作者:数据小太阳 更新时间:2023-10-29 03:09:03 26 4
gpt4 key购买 nike

我正在尝试创建一个函数,它充当执行函数的代理。

它接受一个指向值的指针(这将是设置结果的地方)、一个函数和一些参数。它执行函数并将结果应用于值。

我的第一个挑战是执行函数,因为声明的类型不是 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)
}

最佳答案

使用Value.Call调用函数。通过在 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()

Run it on the Playground .

如果类型不匹配、参数数量不匹配或返回值数量不匹配,上述代码将出现 panic。可以通过使用 reflect 包检查类型来避免 panic ,但我会把它留作练习。

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

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

关于go - 我如何编写一个函数代理,它采用一个转换为 func(...x) ...y 的接口(interface){},并将结果绑定(bind)到一个指针值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55485351/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com