Go 中新的波形符 ~ 的含义是什么?

Jer*_* An 45 generics go

Go 引入了新的令牌~

~T 表示具有基础类型 T 的所有类型的集合

不过我看不懂,请高人帮忙解释一下。

下面是一个例子。

type Ordered interface {
      Integer | Float | ~string
}
Run Code Online (Sandbox Code Playgroud)

bla*_*een 57

在 Go 泛型中,~波形符标记在表单中用于~T表示基础类型为 的类型集T

\n

它在泛型提案中也被称为“近似”约束元素,它用简单的语言解释了它的好处:

\n
\n

列出单一类型本身是没有用的。为了满足约束条件,我们希望不仅能够表示 int,还能够表示基础类型为 int\xe2\x80\x9d 的 \xe2\x80\x9cany 类型。[...] 如果程序使用type MyString string,则该程序可以使用<具有类型值的运算符MyString。应该可以使用类型实例化[函数] MyString

\n
\n

如果您想要正式参考,语言规范已将基础类型的定义放在其自己的部分中:

\n
\n

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

\n
\n

这涵盖了类型文字和其他具有绑定标识符的复合类型的常见情况,或者您通过预先声明的标识符定义的类型,这是泛型提案中提到的情况:

\n
// underlying type = struct literal -> itself -> struct { n int }\ntype Foo struct {\n    n int\n}\n\n// underlying type = slice literal -> itself -> []byte\ntype ByteSlice []byte\n\n// underlying type = predeclared -> itself -> int8\ntype MyInt8 int8\n\n// underlying type = predeclared -> itself -> string\ntype MyString string\n
Run Code Online (Sandbox Code Playgroud)\n

实际含义是,类型集仅包含精确元素的接口约束不允许您自己定义的类型:

\n
// hypothetical constraint without approximation elements\ntype ExactSigned interface {\n    int | int8 | int16 | int32 | int64\n}\n\n// CANNOT instantiate with MyInt8\nfunc echoExact[T ExactSigned](t T) T { return t }\n\n// constraints.Signed uses approximation elements e.g. ~int8\n// CAN instantiate with MyInt8\nfunc echo[T constraints.Signed](t T) T { return t }\n
Run Code Online (Sandbox Code Playgroud)\n

与其他约束元素一样,您可以在并集中使用近似元素,如下所示constraints.Signed或不带有语法糖的匿名约束中一样。值得注意的是,只有一个 approx 元素的语法糖是有效的:

\n
// anonymous constraint\nfunc echoFixedSize[T interface { ~int8 | ~int32 | ~int64 }](t T) T { \n    return t \n}\n\n// anonymous constraint with syntactic sugar\nfunc echoFixedSizeSugar[T ~int8 | ~int32 | ~int64](t T) T { \n    return t \n}\n\n// anonymous constraint with syntactic sugar and one element\nfunc echoFixedSizeSugarOne[T ~int8](t T) T { \n    return t \n}\n
Run Code Online (Sandbox Code Playgroud)\n

正如上面所预期的,近似元素的常见用例是需要具有方法的复合类型(切片、结构体等)。在这种情况下,您必须绑定标识符:

\n
// must bind identifier in order to declare methods\ntype ByteSeq []byte\n\nfunc (b ByteSeq) DoSomething() {}\n
Run Code Online (Sandbox Code Playgroud)\n

现在近似元素可以方便地允许实例化ByteSeq

\n
// ByteSeq not allowed, or must convert func argument first\nfunc foobar[T interface { []byte }](t T) { /* ... */ }\n\n\n// ByteSeq allowed\nfunc bazquux[T interface { ~[]byte }](t T) { /* ... */ }\n\nfunc main() {\n    b := []byte{0x00, 0x01}\n    seq := ByteSeq{0x02, 0x03}\n\n    foobar(b)           // ok\n    foobar(seq)         // compiler error\n    foobar([]byte(seq)) // ok, allows inference\n    foobar[[]byte](seq) // ok, explicit instantiation, then can assign seq to argument type []byte\n\n    bazquux(b)          // ok\n    bazquux(seq)        // ok\n}\n
Run Code Online (Sandbox Code Playgroud)\n

笔记:您不能将近似标记与类型参数一起使用:

\n
// INVALID!\ntype AnyApprox[T any] interface {\n    ~T\n}\n
Run Code Online (Sandbox Code Playgroud)\n


Hym*_*sco 10

不仅有新的令牌,还有接口的新语法。除了方法约束之外,您还可以声明具有类型约束的接口。

为了满足接口,类型必须同时满足方法约束和类型约束。

来自文档

表示所有具有底层类型 int 且实现 String 方法的类型的接口。

interface {
  ~int
  String() string
}
Run Code Online (Sandbox Code Playgroud)

对于具有“底层类型”为 的类型int,这意味着该类型采用以下形式:

type SomeType int
Run Code Online (Sandbox Code Playgroud)

为了满足方法约束,必须声明一个具有指定签名的方法:

func (v SomeType) String() string {
  return fmt.Sprintf("%d", v)
}
Run Code Online (Sandbox Code Playgroud)