Go 1.18 泛型中的逆变类型
在 Go 1.18 中,泛型的引入引发了人们对逆变类型的兴趣。出现的一个关键问题是它们如何在泛型上下文中发挥作用。
不利的行为:不兼容的类型
考虑以下代码片段:
func Pipe[A, T1, T2 any](left func(A) T1, right func(T1) T2) func(A) T2 { return func(a A) T2 { return right(left(a)) } }
当尝试将 Pipe 与以下内容一起使用时函数:
func OpenFile(name string) *os.File { ... } func ReadAll(rdr io.Reader) []byte { ... }
编译失败,因为编译器将 T1 视为 *os.File,它与 io.Reader 不同。
根本原因:逆变语义
问题源于逆变类型的本质。在这种情况下,T1 预计是比 A 更具体的类型,这意味着接受 T1 的函数也可以接受 A。但是,Go 泛型不支持协变结果类型。因此,返回 T1 的函数不能返回 A,即使它们是隐式可转换的。
解决方案和后果
目前无法修改 Pipe 的签名转到 1.18 以允许所需的行为。这不被视为错误,而是一种有意的设计选择。
解决方法:类型转换
要规避此限制,可以在运行时诉诸类型转换:
func Pipe[A, T1, T2, T3 any](left func(A) T1, right func(T2) T3) func(A) T3 { return func(a A) T3 { return right(any(left(a)).(T2)) } }
但是,这种方法牺牲了编译时类型安全性。
以上是逆变类型在 Go 1.18 泛型中如何工作?的详细内容。更多信息请关注PHP中文网其他相关文章!