登录
首页 >  Golang >  Go问答

深入理解泛型:类型 *T 引用的是类型参数的指针,而非类型参数本身

来源:stackoverflow

时间:2024-02-11 22:36:25 492浏览 收藏

大家好,我们又见面了啊~本文《深入理解泛型:类型 *T 引用的是类型参数的指针,而非类型参数本身》的内容中将会涉及到等等。如果你正在学习Golang相关知识,欢迎关注我,以后会给大家带来更多Golang相关文章,希望我们能一起进步!下面就开始本文的正式内容~

问题内容

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

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

我想为共享公共 id 字段的不同类型(此处为 a 和 b)实现一个对象存储。遵循 dry 的想法,我想使用泛型来实现商店。

添加对象时,我想使用 gs 接口设置其 id 字段(当然实际代码要复杂一点),但编译器不希望我这样做。

./prog.go:29:7: item.setid undefined (类型 *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())
}

正确答案


关于使用 *t

简而言之,类型参数不是它的约束。该约束仅确定 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 上声明的。因此,您应该使用 *a 实例化 mystore

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

到这里,我们也就讲完了《深入理解泛型:类型 *T 引用的是类型参数的指针,而非类型参数本身》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>