【问题标题】:Unable to assign to generic struct field [duplicate]无法分配给通用结构字段[重复]
【发布时间】:2022-10-18 03:24:01
【问题描述】:

给定一个通用结构:

type R2[IDTYPE comparable] struct {
    ID        IDTYPE
    IsActive  bool
}

实现接口:

type Storable interface {
    Store(ctx context.Context) error
}

我希望以下定义有效:

func (r R2[int]) Store(ctx context.Context) error {
    r.ID = 123 // not allowed
    // ...
    return nil
}

但是,方法定义是不允许的。错误是:

'123' (type untyped int) cannot be represented by the type IDTYPE (int)

在 Go 中还不能进行这种通用字段分配吗?

附录: 在去操场上,错误是:

cannot use 123 (untyped int constant) as int value in assignment

并且转换为int(123) 不起作用。这种情况下的错误是:

cannot use comparable(123) (untyped int constant 123) as int value in assignment

【问题讨论】:

    标签: go generics


    【解决方案1】:

    Instantiation 必须发生在类型级别,而不是方法级别,并且方法不能引入新的类型参数,请参阅 How to create generic method in Go? (method must have no type parameters)

    这意味着当您想使用 R2 时,您必须为类型参数选择类型参数,而方法无法更改这些,您会“卡住”在 R2 的实例化中选择的类型.

    另请注意,由于IDTYPE 的约束是comparable,例如可能是string,因此整数123 在所有情况下都不能分配给ID 字段,因为它可能具有@987654331 类型@。

    如果您想要/必须为 ID 处理多个具体类型,泛型不是正确的选择。可以使用接口代替:

    type R2 struct {
        ID       any
        IsActive bool
    }
    

    另请注意,如果您希望修改接收器(例如结构的字段),则接收器必须是指针。

    如果您希望将存储在ID 中的值限制为comparable,请使用(通用)函数。

    以下是您的操作方法:

    type R2 struct {
        ID       any
        IsActive bool
    }
    
    func (r *R2) Store(ctx context.Context) error {
        setID(r, 123)
        return nil
    }
    
    func setID[ID comparable](r *R2, id ID) {
        r.ID = id
    }
    

    测试它:

    r := &R2{}
    var s Storable = r
    
    s.Store(context.TODO())
    
    fmt.Println(r)
    

    哪些输出(在Go Playground 上尝试):

    &{123 false}
    

    这提供了灵活性(您可以使用setID()ID 字段设置任何可比较的值),并提供编译时安全性:尝试设置不可比较的值将导致编译时错误,例如:

    setID(r, []int{1}) // Error: []int does not implement comparable
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      • 2018-01-24
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多