英文:
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])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论