我尝试编写一个函数,它接受任何其他函数并在其周围包装一个新函数。这是我到目前为止所尝试的:
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
为什么没有参数的函数与具有可变数量参数的函数不兼容?我该怎么做才能使它们兼容?
更新 受保护的功能应与原始功能兼容:
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) }
答案 0 :(得分:12)
Go中的类型非常具体。你可以试试
a := func(_ ...interface{}) {
fmt.Println("unprotected")
}
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")
}
输出
Protected
unprotected
Protected
hello
编辑:回答更新
就像我上面说的那样,Go中的类型非常具体。 protect函数返回一个类型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
}
}
然后进行转换功能:
func convert(f func(...interface{}) (func(int) int) {
return func(x int) int {
r := f(x)
return r[0].(int)
}
}
然后你的电话看起来像
take_func_int_int(convert(b))
退一步,尝试重做问题。在这些例子中,我完全杀死了类型安全。你想要完成什么?
答案 1 :(得分:-1)
package main
import "fmt"
// Here's a function that will take an arbitrary number
// of `int`s as arguments.
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
func main() {
// Variadic functions can be called in the usual way
// with individual arguments.
sum(1, 2)
sum(1, 2, 3)
// If you already have multiple args in a slice,
// apply them to a variadic function using
// `func(slice...)` like this.
nums := []int{1, 2, 3, 4}
sum(nums...)
}