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)) } }
此函数旨在将左侧函数的输出通过管道传输到右侧函数,从而链接计算。但是,当尝试将其与以下示例一起使用时:
func OpenFile(name string) *os.File { ... } func ReadAll(rdr io.Reader) []byte { ... } var OpenRead = Pipe(OpenFile, ReadAll)
编译失败。这是因为编译器期望 T1 与 *os.File 相同,即使它与 io.Reader 兼容。虽然期望兼容类型被接受似乎是合理的,但由于 Go 缺乏对协变结果类型的支持,情况并非如此。
有没有办法在 Go 1.18 中修复此签名?
不幸的是,没有。 Go 的泛型目前缺乏使用类型参数表达类型可转换性的能力,因此无法修改 Pipe 函数以允许这种行为。
这是 Go 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中文网其他相关文章!