Golang 1.18 ジェネリックの共分散: その制限を理解する
Golang 1.18 のジェネリックの導入は多くの進歩をもたらしましたが、次のような特定の制限が残っています。完全な共分散の欠如support.
問題の理解
次の 2 つの関数を取る Pipe という汎用関数を定義するシナリオを考えてみましょう:
目的は、左の出力を右への入力として実行する関数を作成することです。ただし、次の実装は場合によってはコンパイルに失敗します:
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 の決定安全性の考慮に基づいています。共分散を許可すると、意図したシグネチャと一致しない型で関数が呼び出される状況が発生し、未定義の動作が発生する可能性があります。
FAQ の説明
Golang FAQ には明示的に記載されています。現在の動作は意図的なものであり、バグではありません。この決定は、アプリケーションの信頼性を損なう可能性のある予期しない実行時エラーを防ぐことを目的としています。
変換可能な型と共変型
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 中国語 Web サイトの他の関連記事を参照してください。