【问题标题】:Assigning a value literal to a struct field of a generic type without running into an IncompatibleAssign error将值文字分配给泛型类型的结构字段而不会遇到 IncompatibleAssign 错误
【发布时间】:2022-10-18 03:33:27
【问题描述】:

这可以:

type constraint interface {
    ~float32 | ~float64
}

type foo[T constraint] struct {
    val T
}

func (f *foo[float64]) setValToPi() {
    f.val = 3.14
}

但是,如果我将 constraint 更改为也包含 int 类型,则会遇到错误:

type constraint interface {
    ~float32 | ~float64 | ~int
}

type foo[T constraint] struct {
    val T
}

func (f *foo[float64]) setValToPi() {
    f.val = 3.14 // IncompatibleAssign: cannot use 3.14 (untyped float constant) as float64 value in assignment
}

为什么包含不属于同一“类型组”的类型的约束会导致此错误,我应该如何处理?

【问题讨论】:

    标签: go generics


    【解决方案1】:

    这个语法:

    func (f *foo[float64]) setValToPi() {
        // ...
    }
    

    只是一个方法声明。它确实不实例化泛型类型foo。方括号中的标识符float64 是类型参数的名称。它也可以是T,就像在类型定义中一样。

    就像你写的:

    type foo[float64 constraint] struct {
        val float64
    }
    

    由于float64 是一个预先声明的标识符,您可以使用类型参数名称隐藏它。

    所以在方法setValToPi 中,关于val 类型的唯一已知信息是它被限制为constraint,例如~float32 | ~float64 | ~int 的联合体。

    如果将方法声明更改为:

    func (f *foo[T]) setValToPi() {
        // ...
    }
    

    你会得到与T 相同的错误:

    不能在赋值中使用 3.14(无类型浮点常量)作为 T 值

    错误是由于3.14(一个无类型的浮点常量)不能总是分配给全部foo[T] 的可能实例,特别是 T 确实是 ~int 的实例。

    float64 标识符作为类型参数的游乐场:https://gotipplay.golang.org/p/1EuAsSKdihK

    一个解决方案是让方法接受类型参数类型的值(除了使用不太容易混淆的标识符):

    func (f *foo[T]) SetValue(val T) {
        f.val = val
    }
    

    这当然意味着您不能设置像3.14 这样的固定值,但正如所解释的,这首先是一个错误。其他可能的解决方案是使用 any/interface{} 作为字段类型。如需灵感,请参阅herehere

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-11
      • 2019-06-08
      • 1970-01-01
      • 2019-10-16
      • 2018-05-06
      • 2018-09-02
      • 1970-01-01
      • 2019-02-05
      相关资源
      最近更新 更多