登录
首页 >  Golang >  Go问答

如何在Go泛型中使用通用方法来约束联合类型?

来源:stackoverflow

时间:2024-02-11 17:09:24 434浏览 收藏

Golang不知道大家是否熟悉?今天我将给大家介绍《如何在Go泛型中使用通用方法来约束联合类型?》,这篇文章主要会讲到等等知识点,如果你在看完本篇文章后,有更好的建议或者发现哪里有问题,希望大家都能积极评论指出,谢谢!希望我们能一起加油进步!

问题内容

我试图了解 go 泛型(v1.18)中类型联合约束的用法。这是我尝试过的代码:

type A struct {
}

type B struct {
}

type AB interface {
    *A | *B
}

func (a *A) some() bool {
    return true
}

func (b *B) some() bool {
    return false
}

func some[T AB](x T) bool {
    return x.some()   // <- error
}

编译器抱怨:

x.some undefined(类型 t 没有字段或方法 some)

这是为什么呢?如果我无法使用 *a*b 类型的共享方法,那么定义类型 union *a | 的意义何在? *完全是b吗?

(显然我可以使用共享方法定义一个接口并直接使用它。但在我的特定用例中,我想明确限制为某些类型。)


正确答案


将方法添加到接口约束中,而不放弃泛型:

type ab interface {
    *a | *b
    some() bool
}

func some[t ab](x t) bool {
    return x.some()   // works
}

这将 t 限制为 *a*b 类型,并声明 some() bool 方法。

但是,正如您已经发现的,这是一种解决方法。你是对的,它应该单独与类型联合一起使用。这是 go 1.18 的限制。令人困惑的部分是语言规范似乎仍然支持您的理论(Method sets):

接口类型的方法集是接口类型集中每个类型的方法集的交集(结果方法集通常只是接口中声明的方法集)。

此限制似乎仅记录在 Go 1.18 release notes 中:

当前的泛型实现具有以下限制:

[...] go 编译器目前仅支持在参数类型为 p 的值 x 上调用方法 m 如果 m 是由 p 的约束接口显式声明的。 [...] 即使 m 可能位于 p 的方法集中,因为 p 中的所有类型都实现 m。我们希望在 go 1.19 中取消此限制。

go 跟踪器中的相关问题是 #51183,其中有 Griesemer's confirmation,并决定保留语言规范不变,并记录限制。

ab 的声明更改为

type ab interface {
    *a | *b
    some() bool
}

在 generic go 中,约束就是接口。如果类型参数实现了其约束,则它是有效的。

请观看关于泛型的 gophercon 视频以更好地理解:

为了确保我理解您的问题,请运行 Go Playground in “Go Dev branch” mode 中的以下代码片段:

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

type A struct {
}

type B struct {
}

type C struct{}

type AB interface {
    *A | *B
    some() bool
}

func (a *A) some() bool {
    return true
}

func (b *B) some() bool {
    return false
}

func (c *C) some() bool {
    return false
}

func some[T AB](x T) bool {
    return x.some()
}

func main() {
    p := new(A)
    fmt.Println(some[*A](p))

    //uncomment the lines below to see that type C is not valid
    //q := new(C)
    //fmt.Println(some(q))

}

到这里,我们也就讲完了《如何在Go泛型中使用通用方法来约束联合类型?》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

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