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 类型。[...] 如果程序使用
\ntype MyString string
,则该程序可以使用<
具有类型值的运算符MyString
。应该可以使用类型实例化[函数]MyString
。
如果您想要正式参考,语言规范已将基础类型的定义放在其自己的部分中:
\n\n\n每个类型 T 都有一个基础类型:如果 T 是预声明的布尔、数字或字符串类型之一,或者类型文字,则相应的基础类型是 T 本身。否则,T\ 的基础类型是T 在其类型声明中引用的类型的基础类型类型的基础类型。
\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 元素的语法糖是有效的:
// 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
:
// 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 方法的类型的接口。
Run Code Online (Sandbox Code Playgroud)interface { ~int String() string }
对于具有“底层类型”为 的类型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)
归档时间: |
|
查看次数: |
10488 次 |
最近记录: |