英文:
How to pass a variadic function with different type of arguments as a value in golang?
问题
我想将一个可变参数函数作为另一个函数的参数传递。我尝试了以下代码,但它没有起作用。请给我一些建议。
type Action func(args ...any) error
func ActionType(f Action) reflect.Type {
return reflect.TypeOf(f)
}
func main() {
f1 := func(int, string) error {}
f2 := func(int) error {}
f3 := func() error {}
fmt.Println(ActionType(f1), ActionType(f2), ActionType(f3)) //error here
}
我想知道如何解决这个问题。
英文:
I want to pass a variadic function as the parameter of another function.I tried like the following code, but it didn't work.Please give me some of advice.
type Action func(args ...any) error
func ActionType(f Action) reflect.Type {
return reflect.TypeOf(f)
}
func main() {
f1 := func(int, string) error {}
f2 := func(int) error {}
f3 := func() error {}
fmt.Println(ActionType(f1), ActionType(f2), ActionType(f3)) //error here
}
答案1
得分: 1
你正在声明f1
、f2
和f3
作为匿名函数,它们的类型分别为func(int, string) error
、func(int) error
和func() error
,其中没有一个是func(...any) error
。要创建一个Action
,你需要这样做:f4 := func(...any) error { //stuff }
。在Go语言中,类型非常严格,其可变参数函数基本上只是接受一个切片参数(作为最后一个参数)的语法糖。大致上,func(...any)
等同于func([]any)
,尽管它们甚至不是相同的类型。
错误消息基本上告诉你这一点,尽管更简洁。
./prog.go:18:25: 无法将类型为 func(int, string) error 的 f1 用作参数传递给 ActionType 中的 Action 类型
./prog.go:18:41: 无法将类型为 func(int) error 的 f2 用作参数传递给 ActionType 中的 Action 类型
./prog.go:18:57: 无法将类型为 func() error 的 f3 用作参数传递给 ActionType 中的 Action 类型
Icza在评论中提出了一种使ActionType()
接受任何函数的方法。我之前使用过的另一种方法,可能更加类型安全,是使ActionType()
接受一个没有参数的函数(并返回一个错误,或者其他你需要返回的内容)。然后,使用闭包来捕获Action
函数的"参数"。例如:
package main
import (
"fmt"
"reflect"
)
type Action func() error
func ActionType(f Action) reflect.Type {
// 调用 f 执行操作
err := f()
if err != nil {
fmt.Println(err)
}
// 做其他事情...
return reflect.TypeOf(f)
}
// 这本质上是相同的,因为 Action 的底层类型是 "func() error"
func ActionType2(f func() error) reflect.Type { return reflect.TypeOf(f) }
func main() {
msg := "hello world"
number := 42
action1 := func() error {
fmt.Println(msg)
return nil
}
action2 := func() error {
number *= 2
return nil
}
fmt.Println(ActionType(action1))
fmt.Println(ActionType(action2))
fmt.Println(ActionType2(action2)) // 不修改 number
fmt.Println(number)
}
输出
hello world
main.Action
main.Action
func() error
84
英文:
You're declaring f1
, f2
, and f3
as anonymous functions with types func(int,string) error
, func(int) error
, and func() error
respectively, none of which is func(...any) error
. To create an Action
you'd have to do f4 := func(...any) error { //stuff }
for example. Types are pretty strict in Go, and its variadic functions are basically just syntactic sugar for accepting a single slice argument (as the last arg). Roughly, func(...any)
equals func([]any)
, though even these aren't even the same type.
The error messages basically tell you this, though more tersely.
./prog.go:18:25: cannot use f1 (variable of type func(int, string) error) as type Action in argument to ActionType
./prog.go:18:41: cannot use f2 (variable of type func(int) error) as type Action in argument to ActionType
./prog.go:18:57: cannot use f3 (variable of type func() error) as type Action in argument to ActionType
Icza suggested in the comments one way to make ActionType()
take any function. Another way that I have used before, and is perhaps a little more type safe, is to make ActionType()
take a function with no arguments (and return an error, or whatever else you need to return). Then, use a closure to capture the "arguments" for the Action
func. For example:
package main
import (
"fmt"
"reflect"
)
type Action func() error
func ActionType(f Action) reflect.Type {
// call f to perform the action
err := f()
if err != nil {
fmt.Println(err)
}
// do other things ...
return reflect.TypeOf(f)
}
// this is essentially the same since Action's underlying type
// is "func() error"
func ActionType2(f func() error) reflect.Type { return reflect.TypeOf(f) }
func main() {
msg := "hello world"
number := 42
action1 := func() error {
fmt.Println(msg)
return nil
}
action2 := func() error {
number *= 2
return nil
}
fmt.Println(ActionType(action1))
fmt.Println(ActionType(action2))
fmt.Println(ActionType2(action2)) // doesn't modify number
fmt.Println(number)
}
Output
hello world
main.Action
main.Action
func() error
84
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论