Home > Article > Backend Development > Why Does the `Pipe` Function Fail to Compile with Compatible Types in Go 1.18 Generics?
Go 1.18 introduced generics, which allows for the creation of type-safe code. However, certain behaviors may differ from expectations, such as with contravariant types.
Consider the following function in 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)) } }
This function is designed to pipe the output of left as the input to right. However, it fails to compile when used as follows:
func OpenFile(name string) *os.File { ... } func ReadAll(rdr io.Reader) []byte { ... } var OpenRead = Pipe(OpenFile, ReadAll)
This is because the compiler determines that T1 is *os.File, which is not identical to io.Reader even though it is compatible.
The desired behavior would be the ability to chain the Pipe function with functions that accept a compatible type as input. This aligns with the expected behavior when invoking the chain without generics.
Questions:
Answers:
Workaround:
While it is not possible to achieve "compile-time type-safe" behavior, one possible workaround is to use type assertion:
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)) } }
This code is not type-safe at compile time, but it may provide the desired functionality in some cases.
The above is the detailed content of Why Does the `Pipe` Function Fail to Compile with Compatible Types in Go 1.18 Generics?. For more information, please follow other related articles on the PHP Chinese website!