下面的代码导致错误"INVALID COMPACTIVE TEXAL TYPE T".

package main

import "fmt"

func main() {
    fmt.Println(createThing[foo]())
}

type thing interface {
    foo | bar
}

type foo struct {
    id int
    a  string
}

type bar struct {
    id int
    b  int
}

func createThing[T thing, P *T]() P {
    return &T{}
}

如果我只在接口thing中包含foo,或者删除a stringb int以使foobar完全相同,则代码将运行而不会出错.然而,这不是违背了泛型的目的吗?为什么我不能像这样实例化泛型类型,尤其是在我甚至不访问任何字段的情况下?

可能与https://github.com/golang/go/issues/48522有关

推荐答案

大多数泛型类型都不是复合文字的有效类型.不过,这不是问题,因为还有其他方法可以创建泛型类型的值.

要创建指向新零值的指针,请执行以下操作:

func createThing[T thing]() *T {
    return new(T)
}

或创建非指针零值:

func createThing[T thing]() T {
    var value T
    return value
}

对于why,错误是以这种方式发生的,以下是规范中的解释,针对您的特定问题进行了修改.

对于composite literals人:

WritalType的核心类型T必须是 struct 、数组、切片或映射类型

core type是多少?

如果[...],则接口T具有核心类型只有一个类型U,它是T类型集中所有类型的底层类型

没有其他接口具有核心类型.

underlying type是多少?

每个类型T都有一个基础类型:如果T是预声明的布尔、数值或字符串类型之一,或者是类型文字,则对应的基础类型就是T本身.否则,T的基础类型是T在其声明中引用的类型的基础类型.

"类型文字"可以指文字 struct 类型,如struct{int id}.因此,当foobarunderlying type都为struct{int id}时,thingcore typestruct{int id},因此复合文字是可能的.当foobar不具有相同的底层类型时,则thing没有核心类型,并且复合文字是不可能的,这就是您的错误.

形式上的定义可能看起来很复杂,但结果和实际意义很简单:泛型代码只能跨可能的类型表达公共行为.此外,在所有基础类型都相同的特殊情况下,文字值并不是常见的行为.

Go相关问答推荐

golang-jWT签名无效

更改位置级别和时间戳零点Golang

mockgen不创建模拟

为什么没有正确生成这些元组?

GORM:一个表的两个外键

不接受来自 stdin 的重复输入

Go 中的 protobuf FieldMask 解组

这是实现超时的常见方法,为什么 time.After 不起作用

io.Reader 无限循环与 fmt.Fscan

用于提取 <*n 的正则表达式(其中 n 是一个数字)

如何以干净的方式在中间件中注入 repo 或服务?

go - 仅在函数即将返回错误时清理资源

Go Colly 如何找到请求的元素?

gorm 获取列名

Go AST:获取所有 struct

Ginkgo/Gomega panic 测试失败

go mod tidy 错误消息:但是 go 1.16 会 Select

退格字符在围棋操场中不起作用

如何允许可转换为指针的泛型类型参数化另一种可转换为指针的泛型类型?

即使没有竞争条件也没有得到任何输出