使用 Go 1.18 泛型,如何使用约束类型作为需要具体类型的函数的参数?

mof*_*ury 7 generics go

去版本:1.18

这是一个愚蠢的例子,并不是特别有用。我用它作为学习泛型的练习。

我有一个Pokemon界面

type Pokemon interface {
    ReceiveDamage(float64)
    InflictDamage(Pokemon)
}
Run Code Online (Sandbox Code Playgroud)

Charmander带有实现Pokemon接口的类型参数。

type Float interface {
    float32 | float64
}

type Charmander[F Float] struct {
    Health      F
    AttackPower F
}
Run Code Online (Sandbox Code Playgroud)

我想利用Charmander的攻击力来造成伤害。

func (c *Charmander[float64]) ReceiveDamage(damage float64) {
    c.Health -= damage
}

func (c *Charmander[float64]) InflictDamage(other Pokemon) {
    other.ReceiveDamage(c.AttackPower)
}
Run Code Online (Sandbox Code Playgroud)

我的编译器给出错误

无法使用 c.AttackPower(受 Float 约束的 float64 类型变量)作为 other.ReceiveDamage 编译器参数中的 float64 值(IncompleteAssign)

我已经将 struct generic 实例化为*Charmander[float64]. 我希望编译器知道AttackPower是一个float64.

当我将 a 传递float64给需要 的函数时float64,它为什么会抱怨?另一方面,ReceiveDamage也不抱怨。我正在从中减去 a float64,其中Healtha 是受约束类型。

bla*_*een 4

您必须使用类型转换。该方法ReceiveDamage需要 afloat64但主要类型在 中参数化F。某种 类型的东西F,即使仅限于浮点数,或者即使仅限于一个特定的浮点数,也不是float64。这是F。(此外,它也可以用 实例化float32)。

两种转换都会编译,因为float64可以转换为类型参数的类型集中的所有类型,float32并且float64,反之亦然。

所以方法变成:

func (c *Charmander[T]) ReceiveDamage(damage float64) {
    c.Health -= T(damage)
}

func (c *Charmander[T]) InflictDamage(other Pokemon) {
    other.ReceiveDamage(float64(c.AttackPower))
}
Run Code Online (Sandbox Code Playgroud)

固定游乐场:https://go.dev/play/p/FSsdlL8tBLn

请注意,用 实例化时,转换T(damage)可能会导致精度损失。(在这个特定的用例中这可能不会成为问题......)Tfloat32

  • @Inian你的意思是在接收器类型参数中使用名称“float64”?是的,我认为这是一个不好的做法,因为在这种情况下“float64”只是一个名称,而不是类型。另请参阅:/sf/ask/4926640281/#70381052 (2认同)