[英]How to define a function type which accepts any number of arguments in Go?
I try to write a function which takes any other function and wraps a new function around it.我尝试编写一个函数,它接受任何其他函数并围绕它包装一个新函数。 This is what I have tried so far:这是我迄今为止尝试过的:
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 ();
}
When I compile this I get the error:当我编译这个时,我收到错误:
cannot use a (type func()) as type func(...interface { }) in function argument
Why is a function without arguments not compatible to a function with a variable number of arguments?为什么没有参数的函数与具有可变数量参数的函数不兼容? What can I do to make them compatible?我该怎么做才能使它们兼容?
Update: The protected function should be compatible with the original:更新:受保护的功能应与原始功能兼容:
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)
}
Types are pretty concrete in Go. Go 中的类型非常具体。 You could try你可以试试
a := func(_ ...interface{}) {
fmt.Println("unprotected")
}
func (...interface{})
does not mean "any function that takes any number of any kind of arguments", it means "only a function which takes a variable number of interface{} arguments" func (...interface{})
并不意味着“任何函数接受任意数量的任何类型的参数”,它的意思是“只有一个函数接受可变数量的 interface{} 参数”
Alternatively rather than func(...interface{})
you can just use interface{}
and the reflect
package.或者,您可以只使用interface{}
和reflect
包,而不是func(...interface{})
。 See http://github.com/hoisie/web.go for an example.有关示例,请参见http://github.com/hoisie/web.go 。
EDIT: Specifically, this:编辑:具体来说,这个:
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")
}
Ouput is输出是
Protected
unprotected
Protected
hello
EDIT: To answer the update编辑:回答更新
Like I said above, types are pretty concrete in Go.就像我上面说的那样,Go 中的类型非常具体。 The protect function returns a type func(...interface{})
which will never be assignable to func(int)int
.保护函数返回一个类型func(...interface{})
,它永远不能分配给func(int)int
。 I think you're probably either over-engineering your problem or misunderstanding it.我认为你可能要么过度设计了你的问题,要么误解了它。 However, here's a highly discouraged code snippet that would make it work.然而,这是一个非常不鼓励的代码片段,可以让它工作。
First change protect to also return values:首先将保护更改为也返回值:
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
}
}
Then make a convert function:然后做一个转换函数:
func convert(f func(...interface{}) (func(int) int) {
return func(x int) int {
r := f(x)
return r[0].(int)
}
}
Then your call would look like然后你的电话看起来像
take_func_int_int(convert(b))
Step back and try to rework the problem.退后一步,尝试重新解决问题。 I've completely killed type-safety in these examples.在这些示例中,我已经完全消除了类型安全性。 What are you trying to accomplish?你想达到什么目的?
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...)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.