首頁  >  文章  >  後端開發  >  為什麼 Go 1.18 泛型中 `Pipe` 函數無法與相容型別編譯?

為什麼 Go 1.18 泛型中 `Pipe` 函數無法與相容型別編譯?

DDD
DDD原創
2024-11-17 10:30:04437瀏覽

Why Does the `Pipe` Function Fail to Compile with Compatible Types in Go 1.18 Generics?

Go 1.18 泛型中的逆變型別行為

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

此函數旨在將 left 的輸出透過管道傳遞為輸入到右邊。但使用時卻無法編譯,如下圖:

func OpenFile(name string) *os.File {
    ...
}

func ReadAll(rdr io.Reader) []byte {
    ...
}

var OpenRead = Pipe(OpenFile, ReadAll)

這是因為編譯器判定 T1 是 *os.File,雖然相容,但與 io.Reader 並不相同。

所需的行為是將 Pipe 函數與接受相容類型作為輸入的函數連結。這與呼叫沒有泛型的鏈時的預期行為一致。

問題:

  1. 是否有一種方法可以調整 Pipe 的簽名以允許期望的行為?
  2. 這是設計使然還是錯誤?

答案:

  1. 不,目前沒有在 Go 1.18 中使用泛型來表達類型之間的兼容性的方法。
  2. 這種行為不是一個錯誤。反映了 Go 中缺乏對協變結果類型的支持。

解決方法:

雖然無法實現「編譯時類型安全」 " 行為,一種可能的解決方法是使用類型斷言:

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 泛型中 `Pipe` 函數無法與相容型別編譯?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn