首页  >  文章  >  后端开发  >  逆变类型在 Go 1.18 泛型中如何工作?

逆变类型在 Go 1.18 泛型中如何工作?

Linda Hamilton
Linda Hamilton原创
2024-11-17 15:16:02962浏览

How Do Contravariant Types Work in Go 1.18 Generics?

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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn