Go でジェネリック関数を作成する場合、具象型も受け入れると有益な場合があります。ただし、これらの特定の型の新しいインスタンスを使用してインターフェイスのスライスを初期化しようとすると、問題が発生します。
1 つのアプローチは論理的であるように思えるかもしれません。2 つの型パラメーターを定義することです。 1 つはスライス要素タイプ (X) 用で、もう 1 つはインスタンス化する具象タイプ (Y) 用です。ただし、このアプローチは、Y のインスタンスを型 X の要素に割り当てようとすると失敗します。
<code class="go">func Fill[X, Y any](slice []X){ for i := range slice { slice[i] = new(Y) // not work! } }</code>
この問題は、コンパイラがインターフェイス X とその実装 Y の間の関係を失うために発生します。X とその両方Y は別個の any 型として扱われます。
これに対処するには、関数内で明示的なキャスト操作を使用できます。
<code class="go">func Fill[X, Y any](slice []X) { for i := range slice { slice[i] = any(*new(Y)).(X) } }</code>
ただし、これはこのアプローチは、Y が X を実装していない場合にパニックをトリガーします。これは、*sync.Mutex (ポインター型) を sync.Locker.
に割り当てようとするなどのシナリオで発生します。より堅牢でタイプセーフなソリューションには、コンストラクター関数の利用が含まれます。
<code class="go">func Fill[X any](slice []X, f func() X) { for i := range slice { slice[i] = f() } }</code>
この関数は、指定された型の新しいインスタンスを返すコンストラクター関数を受け入れます。これにより、具象型インスタンスを使用したスライスの簡潔かつ安全な初期化が可能になります。
具象型をポインター型でインスタンス化する場合は、次の点に注意することが重要です。 new(Y) は nil 値になります。これを回避するには、func() X { return &sync.Mutex{} } など、コンストラクター関数を調整して正しいポインター値を返すことができます。
以上が## Go で具象型を使用してインターフェイスのスライスを初期化するには?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。