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

使用泛型:type *T 是指向类型参数的指针,而不是类型参数

使用泛型:type *T 是指向类型参数的指针,而不是类型参数

Go
撒科打诨 2022-11-23 10:25:19

可能是 golang 初学者的问题:)

尝试编译下面的代码时,我遇到了以下编译器错误。

我想为共享公共 ID 字段的不同类型(这里是 A 和 B)实现一个对象存储。按照 DRY 的想法,我想使用泛型来实现商店。

添加一个对象时,我想使用GS接口设置它的ID字段(当然实际代码要复杂一些),但是编译器不希望我这样做。

./prog.go:29:7: item.SetId 未定义(type *T 是指向类型参数的指针,而不是类型参数)

./prog.go:34:24: A没有实现GS(SetId方法有指针接收者)

有推荐的方法来解决这个问题吗?提前致谢!!

package main


import "fmt"


type A struct {

    ID      string

    AMember string

}

type B struct {

    ID      string

    BMember string

}


type GS interface {

    Id() string

    SetId(string)

}


func (s A) Id() string      { return s.ID }

func (s *A) SetId(i string) { s.ID = i }

func (s B) Id() string      { return s.ID }

func (s *B) SetId(i string) { s.ID = i }


type MyStore[T GS] struct {

    values map[string]*T

}


func (s *MyStore[T]) add(item *T) {

    item.SetId("aa")

    s.values["aa"] = item

}


func main() {

    var storeA = &MyStore[A]{}

    storeA.values = make(map[string]*A)

    a := &A{}


    storeA.add(a)


    fmt.Println(a.Id())

}


查看完整描述

1 回答

?
侃侃尔雅

TA贡献1528条经验 获得超14个赞

关于使用 *T

简而言之,类型参数不是它的约束。该约束仅确定 上可用的操作T,它并不暗示关于 的任何内容*T,它现在只是一个未命名的指针类型。这是意义:

type *T 是指向类型参数的指针,而不是类型参数

因此,与您的情况一样,方法集*T不会自动包含在T具体类型上声明的指针接收器方法A,并且它不会实现将由 实现的接口*A

您必须通过设置额外的约束将其明确告知编译器。在简化形式中,它类似于:

func Foo[T any, PT interface { SetId(string); *T}](v T) {}

您可以在此处找到有关此用例的更多示例和变体:

关于实施约束

&MyStore[A]{}错误消息清楚地报告了此实例化失败的原因:

A没有实现GS(SetId方法有指针接收者)

换句话说SetId(),声明于*A,而不是A。因此你应该实例MyStore*A

var storeA = &MyStore[*A]{}

然后*T将结构/方法定义中的出现更改为T

type MyStore[T GS] struct {
    values map[string]T // just T instead of *T
    }
    func (s *MyStore[T]) add(item T) {
}

在使用字段类型实例化时,*A将变得等效于map[string]*A因此使分配storeA.values = make(map[string]*A)有效,并且方法签名add(item *A)因此允许storeA.add(&A{}).

固定游乐场:https ://gotipplay.golang.org/p/dcUVJ5YQK_b


查看完整回答
反对 回复 6天前

添加回答

举报

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