ホームページ > バックエンド開発 > Golang > Golang ジェネリックスとインターフェイスを使用してスライスを具体的な実装で埋めるにはどうすればよいですか?

Golang ジェネリックスとインターフェイスを使用してスライスを具体的な実装で埋めるにはどうすればよいですか?

Mary-Kate Olsen
リリース: 2024-10-26 10:33:02
オリジナル
794 人が閲覧しました

How to Fill a Slice with Concrete Implementations Using Golang Generics and Interfaces?

Golang ジェネリクス: インターフェイスと具象実装の組み合わせ

Go 1.18 では、開発者はジェネリクスを使用して、より広範囲の型で動作する関数とデータ構造を定義できます。ただし、ユーザーがジェネリック型パラメーターに具象型を提供しながら、インターフェイスでジェネリックスを使用しようとする特定のシナリオが浮上しています。

問題

スライスにデータを設定することを目的とした次の関数を考えてみましょう。具象型の新しいインスタンス:

<code class="go">func Fill[X any](slice []*X) {
   for i := range slice {
      slice[i] = new(X)
   }
}</code>
ログイン後にコピー

この関数は、[]*int などの特定の型へのポインターのスライスを埋めるときに期待どおりに機能します。ただし、スライスがインターフェイスで構成され、関数がジェネリック パラメーターの具象型で呼び出された場合、コンパイルは失敗します。

<code class="go">xs := make([]sync.Locker, 10) // fill with nils
Fill[sync.Locker,sync.Mutex](xs) // ouch</code>
ログイン後にコピー

原因

この問題は、両方の型パラメーター X を制約するために発生します。 any に Y を指定すると、インターフェイスとその具体的な実装の間の関係が削除されます。コンパイル時には、X と Y が別個の型であることのみがわかります。

解決策

この問題に対処するには、明示的なアサーションを使用できます。

<code class="go">func Fill[X, Y any](slice []X) {
    for i := range slice {
        slice[i] = any(*new(Y)).(X)
    }
}</code>
ログイン後にコピー

ただし、この解決策では、Y が X を実装していない場合に実行時パニックが発生する可能性があります。さらに、Y がポインター型の場合、基本型の情報が失われ、目的の具象型のインスタンスではなく nil 値が生成されます。

より良いアプローチは、以下に示すように、2 番目の汎用パラメーターの代わりにコンストラクター関数を使用することです。

<code class="go">func main() {
    xs := make([]sync.Locker, 10)
    Fill(xs, func() sync.Locker { return &sync.Mutex{} })
}

func Fill[X any](slice []X, f func() X) {
    for i := range slice {
        slice[i] = f()
    }
}</code>
ログイン後にコピー

このソリューションは、スライスを特定の具象型のインスタンスで埋める、より堅牢かつ慣用的な方法を提供します。タイプセーフティを維持します。

以上がGolang ジェネリックスとインターフェイスを使用してスライスを具体的な実装で埋めるにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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