英文:
Cannot use golang generics variable in function call
问题
我正在尝试理解Go 1.18中的泛型实现。在我的测试示例中,我正在存储一系列的测试用例,并尝试调用一个函数变量。不幸的是,在EvalCases函数中,当我尝试使用变量tc.input时,我收到以下错误:
无法将类型为T(受Inputer约束的变量)的input用作fn的字符串类型参数
为什么会出现这个错误,我该如何修复它?
import (
"fmt"
"strconv"
)
type BoolCase func(string) bool
type Inputer interface {
int | float64 | ~string
}
type Wanter interface {
Inputer | bool
}
type TestCase[T Inputer, U Wanter] struct {
input T
want U
}
type TestConditions[T Inputer, U Wanter] map[string]TestCase[T, U]
// IsNumeric验证字符串是否为有效的int64或float64
func IsNumeric(s string) bool {
_, err := strconv.ParseFloat(s, 64)
return err == nil
}
func EvalCases[T Inputer, U Wanter](cases TestConditions[T, U], fn BoolCase) {
for name, tc := range cases {
input := T(tc.input)
want := tc.want
// 错误:无法将类型为T(受Inputer约束的变量)的input用作字符串类型的fn参数
got := fn(input)
fmt.Printf("name: %-20s | input: %-10v | want: %-10v | got: %v\n", name, input, want, got)
}
}
func main() {
var cases = TestConditions[string, bool]{
"empty": {input: "", want: false},
"integer": {input: "123", want: true},
"float": {input: "123.456", want: true},
}
fn := IsNumeric
EvalCases(cases, fn)
}
英文:
I am trying to understand generics implementation in go1.18. In my test example, I am storing a series of test cases and attempting to call a function variable. Unfortunately, I am getting an error in the EvalCases function when I try to use the variable tc.input, I receive the following error:
> cannot use input (variable of type T constrained by Inputer) as type
> string in argument to fn
Why am I receiving that error, and how do I fix it?
import (
"fmt"
"strconv"
)
type BoolCase func(string) bool
type Inputer interface {
int | float64 | ~string
}
type Wanter interface {
Inputer | bool
}
type TestCase[T Inputer, U Wanter] struct {
input T
want U
}
type TestConditions[T Inputer, U Wanter] map[string]TestCase[T, U]
// IsNumeric validates that a string is either a valid int64 or float64
func IsNumeric(s string) bool {
_, err := strconv.ParseFloat(s, 64)
return err == nil
}
func EvalCases[T Inputer, U Wanter](cases TestConditions[T, U], fn BoolCase) {
for name, tc := range cases {
input := T(tc.input)
want := tc.want
// Error: cannot use input (variable of type T constrained by Inputer) as type string in argument to fn
got := fn(input)
fmt.Printf("name: %-20s | input: %-10v | want: %-10v | got: %v\n", name, input, want, got)
}
}
func main() {
var cases = TestConditions[string, bool]{
"empty": {input: "", want: false},
"integer": {input: "123", want: true},
"float": {input: "123.456", want: true},
}
fn := IsNumeric
EvalCases(cases, fn)
}
答案1
得分: 2
为什么我会收到这个错误?
因为fn
是一个BoolFunc
,它是一个func(string) bool
类型,因此需要一个string
作为参数,但input
的类型是T
。此外,根据你的定义,T
满足Inputer
约束,因此也可以假设类型为int
、float64
或任何非string
类型,其中string
是其底层类型(~string
),但这些类型都不能隐式转换为string
。
如何修复它?
你需要改变BoolCase
的定义,使其自身具有一个泛型类型参数用于其一个参数。你可以将其约束为Inputer
,但也可以使用any
(interface{}
)。
type BoolCase[T any] func(T) bool
然后确保在EvalCases
函数的签名中使用这个泛型类型参数:
func EvalCases[T Inputer, U Wanter](cases TestConditions[T, U], fn BoolCase[T])
https://go.dev/play/p/RdjQXJ0WpDh
英文:
> Why am I receiving that error
Because fn
is a BoolFunc
, which is a func(string) bool
, thus requires a string
as parameter, but input
is of type T
. Furthermore, by your definition, T
satisfies the Inputer
constraint, and thus can also assume type int
, float64
or any non-string
type which has string
as its underlying type (~string
) none of which implicitly cast to string
.
> how do I fix it?
You need to change the definition of BoolCase
to itself have a generic type parameter for its one parameter. You could constraint it to Inputer
, but you could also use any
(interface{}
).
type BoolCase[T any] func(T) bool
Then make sure to serve this generic type parameter in the signature of function EvalCases
:
func EvalCases[T Inputer, U Wanter](cases TestConditions[T, U], fn BoolCase[T])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论