蛊毒传说
在泛型提案中,~波浪号标记用于~T表示基础类型为 的类型集T。它在泛型提案中也被称为“近似”约束元素,它用简单的语言解释了它的好处:列出单一类型本身是没有用的。为了满足约束,我们希望能够说的不仅仅是 int,而是“任何基础类型为 int 的类型”。[...]如果程序使用type MyString string,程序可以使用<带有 type 值的运算符MyString。应该可以用 type 实例化 [a function] MyString。如果您想要正式的参考,语言规范已将基础类型的定义放在其自己的部分中:每个类型 T 都有一个基础类型:如果 T 是预先声明的布尔、数字或字符串类型之一,或者是类型文字,则相应的基础类型是 T 本身。否则,T 的基础类型是T 在其类型声明中引用的类型的基础类型。这涵盖了类型文字和其他具有绑定标识符的复合类型的非常常见的情况,或者您在预声明的标识符上定义的类型,这是泛型提案中提到的情况:// underlying type = struct literal -> itself -> struct { n int }type Foo struct { n int}// underlying type = slice literal -> itself -> []bytetype ByteSlice []byte// underlying type = predeclared -> itself -> int8type MyInt8 int8// underlying type = predeclared -> itself -> stringtype MyString string实际含义是类型集只有精确元素的接口约束不允许您自己定义的类型:// hypothetical constraint without approximation elementstype ExactSigned interface { int | int8 | int16 | int32 | int64}// CANNOT instantiate with MyInt8func echoExact[T ExactSigned](t T) T { return t }// constraints.Signed uses approximation elements e.g. ~int8// CAN instantiate with MyInt8func echo[T constraints.Signed](t T) T { return t }与其他约束元素一样,您可以在联合中使用近似元素,例如constraints.Signed在匿名约束中使用或不使用语法糖。值得注意的是,只有一个 approx 元素的语法糖是有效的:// anonymous constraintfunc echoFixedSize[T interface { ~int8 | ~int32 | ~int64 }](t T) T { return t }// anonymous constraint with syntactic sugarfunc echoFixedSizeSugar[T ~int8 | ~int32 | ~int64](t T) T { return t }// anonymous constraint with syntactic sugar and one elementfunc echoFixedSizeSugarOne[T ~int8](t T) T { return t }如上所述,近似元素的常见用例是需要具有方法的复合类型(切片、结构等)。在这种情况下,您必须绑定标识符:// must bind identifier in order to declare methodstype ByteSeq []bytefunc (b ByteSeq) DoSomething() {}现在近似元素很方便允许实例化ByteSeq:// ByteSeq not allowed, or must convert func argument firstfunc foobar[T interface { []byte }](t T) { /* ... */ }// ByteSeq allowedfunc bazquux[T interface { ~[]byte }](t T) { /* ... */ }func main() { b := []byte{0x00, 0x01} seq := ByteSeq{0x02, 0x03} foobar(b) // ok foobar(seq) // compiler error foobar([]byte(seq)) // ok, allows inference foobar[[]byte](seq) // ok, explicit instantiation, then can assign seq to argument type []byte bazquux(b) // ok bazquux(seq) // ok}注意:您不能将近似标记与类型参数一起使用:// INVALID!type AnyApprox[T any] interface { ~T}