func sum[T int | float64](a, b T) T {
fmt.Println("Type of a: ", reflect.TypeOf(a))
fmt.Println("Type of b: ", reflect.TypeOf(b))
return a + b
}
type Pair[K, V any] struct {
key K
val V
}
func main() {
p := Pair[int, float64]{key: 10, val: 10.2}
fmt.Println(sum(10, 10.2))
fmt.Println(sum(10, -40))
fmt.Println(sum(20, 20.100909999988888))
fmt.Println(sum(p.key, p.val))
}
执行这行Go语言代码时
fmt.Println(sum(p.key, p.val))
,出现错误。有人可以准确解释为什么会发生这种情况吗?
对于语句
fmt.Println(sum(p.key, p.val))
,我希望它打印两个数字的总和。
当您编写通用函数时,例如:
func sum[T int | float64](a, b T) T
您将两个参数
a
和 b
声明为具有相同的类型 T
。
约束
int | float64
允许 T
为 int
或 float64
。但无论是哪一个,参数 a
和 b
都具有相同的一种类型。
换句话说,你的函数
sum
只能用两个int
参数或两个float64
参数来调用。有关这方面的更多信息,请参阅我的回答:any/interface{} 作为约束与参数类型之间的差异?
当你打电话时
p := Pair[int, float64]{key: 10, val: 10.2}
sum(p.key, p.val)
根据您的实例化,结构体字段有两种不同的类型
int
和 float64
Pair[int, float64]
,因此类型推断失败。
那么为什么
sum(10, 10.2)
可以编译?
当仅使用无类型参数调用泛型函数时,从 Go 1.21 开始类型推断遵循常量操作的规则:
如果将多个不同类型的无类型常量参数(例如无类型 int 和无类型浮点常量)传递给具有相同(未另外指定)类型参数类型的参数,现在类型推断会确定类型,而不是出现错误使用与具有无类型常量操作数的运算符相同的方法
这种使用无类型常量操作数的方法被指定为:
如果二元运算(移位除外)的无类型操作数属于不同类型,则结果是此列表后面出现的操作数类型:整数、符文、浮点、复数。该列表实际上就是该句子中冒号后面出现的内容:
integer, rune, floating-point, complex
10
是“整数”类型的无类型常量,
10.2
是“浮点”类型,它出现在上面列表中的“整数”之后,因此类型推断将类型参数
T
确定为是
float64
。此时,实参
10
就可以被赋值给类型为
T = float64
的形参,类型推断成功。
int|float64
常量可以通过常量声明或转换显式指定类型,作为示例,请参阅:或在变量声明或赋值语句中使用时隐式指定类型或作为表达式中的操作数。
https://go.dev/play/p/uq__T_6HYkM
// in the following statement:
// '10' and '10.2' are assigned a suitable type (float64) from this expression:
fmt.Println(sum(10, 10.2))
// Output:
// Type of a: float64
// Type of b: float64
// 20.2
// in the following 3 lines however:
// '10' is given a type at 'x := 10' expression -> int
// '10.2' is given a type at 'y := 10.2' expression -> float64
x := 10
y := 10.2
// and the following line fails to compile:
// fmt.Println(sum(x, y))
// compilation error:
// in call to sum, type float64 of y does not match inferred type int for T
func sum[T int | float64](a, b T) T
如何解释:
sum
是以下之一:
func sum(a, b int) int
func sum(a, b float64) float64