ホームページ >バックエンド開発 >Golang >Go 1.18 ジェネリックで「Pipe」関数が互換性のある型でコンパイルに失敗するのはなぜですか?

Go 1.18 ジェネリックで「Pipe」関数が互換性のある型でコンパイルに失敗するのはなぜですか?

DDD
DDDオリジナル
2024-11-17 10:30:04503ブラウズ

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. パイプの署名を調整して、望ましい動作ですか?
  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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。