反変型は Go 1.18 ジェネリックでどのように機能しますか?

Linda Hamilton
リリース: 2024-11-17 15:16:02
オリジナル
970 人が閲覧しました

How Do Contravariant Types Work in Go 1.18 Generics?

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 を io.Reader と同一ではない *os.File として扱うため、コンパイルは失敗します。

根本原因: 反変セマンティクス

この問題は、反変型の性質に起因します。この場合、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 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート