インターフェイスと具象型のスライスのジェネリック Fill 関数
Golang では、ジェネリックを使用してジェネリック関数を定義できます。インターフェイスのスライスと具象型を扱うときの一般的なタスクは、スライスのすべての要素を具象型で初期化することです。次の関数を考えてみましょう。この関数は、型 X へのポインターのスライスを X の新しいインスタンスで埋めることを目的としています。
<code class="go">func Fill[X any](slice []*X){ for i := range slice { slice[i] = new(X) } }</code>
この関数は、どの型のスライスでも期待どおりに機能します。ただし、この動作をインターフェイスのスライスに拡張し、要素 (Y) の具体的な型を指定しようとすると、課題が発生します。
<code class="go">func Fill[X, Y any](slice []X){ for i := range slice { slice[i] = new(Y) // not work! } }</code>
X と Y の両方を any に制約する場合、インターフェイスと実装者の関係失われます。コンパイラは X と Y を別個の型として扱い、関数本体内で X と Y 間の代入を防止します。
これを解決するには、明示的なアサーションを使用できます。
<code class="go">func Fill[X, Y any](slice []X) { for i := range slice { slice[i] = any(*new(Y)).(X) } }</code>
ただし、このアプローチは可能性があります。 sync.Mutex (ポインタ型) が sync.Locker を実装している場合のように、Y が X を実装していない場合はパニックになります。さらに、ポインター型のゼロ値は nil であるため、このメソッドは、同様に nil 値でスライスを初期化する make([]X, n) を使用する場合に比べて大幅な改善はありません。
より効果的な解決策は、2 番目の型パラメーターの代わりにコンストラクター関数を利用することです。
<code class="go">func Fill[X any](slice []X, f func() X) { for i := range slice { slice[i] = f() } }</code>
この関数は、X のインスタンスを返す関数である追加パラメーター f を受け取ります。これにより、柔軟性が高まります。また、インターフェイスの具体的なタイプの入力をサポートします。たとえば、sync.Mutex 要素を使用して sync.Locker のスライスを初期化するには、次のコードを使用できます。
<code class="go">xs := make([]sync.Locker, 10) Fill(xs, func() sync.Locker { return &sync.Mutex{} })</code>
このアプローチを利用すると、インターフェイスのスライスを具体的なインスタンスで効率的に埋めることができます。 type を使用して、便利でタイプセーフなソリューションを提供します。
以上がGolang で型の安全性を確保し、潜在的なパニックを回避しながら、インターフェースのスライスに具体的な型のインスタンスを効率的に埋め込むにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。