无法在函数调用中使用 Golang 泛型变量。

huangapple go评论87阅读模式
英文:

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约束,因此也可以假设类型为intfloat64或任何非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])

https://go.dev/play/p/RdjQXJ0WpDh

huangapple
  • 本文由 发表于 2022年3月19日 23:36:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/71539540.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定