首页  >  文章  >  后端开发  >  为什么 Golang 1.18 泛型不完全支持协方差?

为什么 Golang 1.18 泛型不完全支持协方差?

Susan Sarandon
Susan Sarandon原创
2024-11-17 18:06:02125浏览

Why Doesn't Golang 1.18 Generics Fully Support Covariance?

Golang 1.18 泛型中的协变:了解其局限性

Golang 1.18 泛型的引入带来了许多进步,但仍然存在某些局限性,包括缺乏完整的协方差支持。

理解问题

考虑一个场景,您想要定义一个名为 Pipe 的通用函数,它接受两个函数:

  • 左:接受 A 类型的参数并返回 T1 类型的值。
  • 右:接受 T1 类型的参数并返回 T2 类型的值。

目标是创建一个函数,将左侧的输出作为右侧的输入执行。但是,以下实现在某些情况下无法编译:

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))
    }
}

出现此问题是因为 Golang 泛型不完全支持协方差。协变意味着类型参数可以用子类型替换而不违反约定。在这种情况下,T1 不允许子类型,而 io.ReadCloser 是 io.Reader 的子类型。

Golang 的设计决策

Golang 决定不完全实现协方差是基于安全考虑。允许协变可能会导致使用与预期签名不匹配的类型调用函数,从而导致未定义的行为。

常见问题解答说明

Golang 常见问题解答明确指出当前的行为是故意的而不是错误。此决定旨在防止可能损害应用程序可靠性的意外运行时错误。

可转换类型与协变类型

虽然 Golang 不支持完全协变,但它允许一种类型到另一种类型的转换。但是,在 func Pipe 的情况下,无法使用类型参数来表示此转换。

作为替代方案,您可以将 left 的结果显式转换为 right 所需的类型。然而,这种方法在编译时不是类型安全的,如以下修改后的代码所示:

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))
    }
}

虽然这可以完成工作,但它牺牲了运行时转换的编译时安全性。

以上是为什么 Golang 1.18 泛型不完全支持协方差?的详细内容。更多信息请关注PHP中文网其他相关文章!

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