如何定义一个在Go中接受任意数量参数的函数类型?

cev*_*ing 7 go

我尝试编写一个函数,它接受任何其他函数并围绕它包装一个新函数.这是我到目前为止所尝试的:

package main

import (
    "fmt"
)

func protect (unprotected func (...interface{})) (func (...interface{})) {
    return func (args ...interface{}) {
        fmt.Println ("protected");
        unprotected (args...);
    };
}

func main () {
    a := func () {
        fmt.Println ("unprotected");
    };
    b := protect (a);
    b ();
}

当我编译这个时,我得到错误:

cannot use a (type func()) as type func(...interface { }) in function argument
Run Code Online (Sandbox Code Playgroud)

为什么没有参数的函数与具有可变数量参数的函数不兼容?我该怎么做才能使它们兼容?

更新: 受保护的功能应与原始功能兼容:

func take_func_int_int (f func (x int) (y int)) (int) {
    return f (1)
}

func main () {

    a := func (x int) (y int) {
        return 2 * x
    }
    b := protect (a)

    take_func_int_int (a)
    take_func_int_int (b)
}

cth*_*m06 12

Go中的类型非常具体.你可以试试

a := func(_ ...interface{}) {
    fmt.Println("unprotected")
}
Run Code Online (Sandbox Code Playgroud)

func (...interface{}) 并不意味着"任何带有任意数量的任何参数的函数",它意味着"只有一个函数接受可变数量的接口{}参数"

或者func(...interface{})你可以只使用interface{}reflect包.有关示例,请参见http://github.com/hoisie/web.go.

编辑:具体来说,这个:

package main

import (
    "fmt"
    "reflect"
)

func protect(oldfunc interface{}) (func (...interface{})) {
    if reflect.TypeOf(oldfunc).Kind() != reflect.Func {
        panic("protected item is not a function")
    }
    return func (args ...interface{}) {
        fmt.Println("Protected")
        vargs := make([]reflect.Value, len(args))
        for n, v := range args {
            vargs[n] = reflect.ValueOf(v)
        }
        reflect.ValueOf(oldfunc).Call(vargs)
    }
}

func main() {
    a := func() {
        fmt.Println("unprotected")
    }
    b := func(s string) {
        fmt.Println(s)
    }
    c := protect(a)
    d := protect(b)
    c()
    d("hello")
}
Run Code Online (Sandbox Code Playgroud)

输出是

Protected
unprotected
Protected
hello
Run Code Online (Sandbox Code Playgroud)

编辑:回答更新

就像我上面说的那样,Go中的类型非常具体.该保护函数返回一个类型func(...interface{}),这将永远是分配给func(int)int.我想你可能要么过度设计你的问题,要么误解它.但是,这是一个非常气馁的代码片段,可以使它工作.

首先改变保护也返回值:

func protect(oldfunc interface{}) (func (...interface{}) []interface{}) {
    if reflect.TypeOf(oldfunc).Kind() != reflect.Func {
        panic("protected item is not a function")
    }
    return func (args ...interface{}) []interface{} {
        fmt.Println("Protected")
        vargs := make([]reflect.Value, len(args))
        for n, v := range args {
            vargs[n] = reflect.ValueOf(v)
        }
        ret_vals := reflect.ValueOf(oldfunc).Call(vargs)
        to_return := make([]interface{}, len(ret_vals))
        for n, v := range ret_vals {
                to_return[n] = v.Interface()
        }
        return to_return
    }
}
Run Code Online (Sandbox Code Playgroud)

然后做一个转换函数:

func convert(f func(...interface{}) (func(int) int) {
    return func(x int) int {
        r := f(x)
        return r[0].(int)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你的电话会是这样的

take_func_int_int(convert(b))
Run Code Online (Sandbox Code Playgroud)

但我保证这不是你真正想要做的.

退一步,尝试重做问题.在这些例子中,我完全杀死了类型安全.你想达到什么目的?