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中文網其他相關文章!