为了账号安全,请及时绑定邮箱和手机立即绑定

同时具有接口和实现的 Golang 泛型

同时具有接口和实现的 Golang 泛型

Go
富国沪深 2022-11-23 19:28:53

我正在尝试编写以下函数:


func Fill[X any](slice []*X){

   for i := range slice {

      slice[i] = new(X)

   }

}


xs := make([]*int, 10) // fill with nils

Fill(xs) // now fill with new(int)

这很好用,但是……如果我想使用一部分接口并提供具体类型?


func Fill[X, Y any](slice []X){

   for i := range slice {

      slice[i] = new(Y) // not work!

   }

}


xs := make([]sync.Locker, 10) // fill with nils

Fill[sync.Locker,sync.Mutex](xs) // ouch


我尝试了一些组合没有成功,有没有办法或者go1.18不支持这样的关系?


查看完整描述

1 回答

?
拉风的咖菲猫

TA贡献1715条经验 获得超2个赞

当您将X和都约束Y到 时any,您将失去所有接口-实现者关系。编译时唯一知道的是X和Y是不同的类型,您不能在函数体内将一个分配给另一个。


使其编译的一种方法是使用显式断言:


func Fill[X, Y any](slice []X) {

    for i := range slice {

        slice[i] = any(*new(Y)).(X)

    }

}

但是,如果Y没有像您的情况X那样真正实现,就会引起恐慌,因为它是(指针类型)实现的。*sync.Mutexsync.Locker


此外,当Y用指针类型实例化 时,您会丢失有关基本类型的信息,因此会丢失零值,包括*new(Y),nil因此您实际上并没有基线改进make(只是类型化的 nils 与 nil 接口)。


你想做的是约束到, like但这是不可能的,因为 1) 类型参数不能用作约束;和/或 2) 约束不能直接嵌入类型参数。它还会像上面那样初始化 nils。YXFill[X any, Y X](slice []X)


更好的解决方案是使用构造函数而不是第二个类型参数:


func main() {

    xs := make([]sync.Locker, 10)

    Fill(xs, func() sync.Locker { return &sync.Mutex{} })

}


func Fill[X any](slice []X, f func() X) {

    for i := range slice {

        slice[i] = f()

    }

}


查看完整回答
反对 回复 2022-11-23

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信