在 Go 中編寫泛型函數時,接受具體類型也是有益的。然而,當嘗試使用這些特定類型的新實例初始化介面切片時,這會帶來挑戰。
一種方法可能看起來合乎邏輯:定義兩個類型參數,一種用於切片元素類型(X),另一種用於要實例化的具體類型(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 被視為不同的任何類型。
為了解決這個問題,可以在函數中使用明確轉換操作:
<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) 將導致零值。為了避免這種情況,可以調整建構子以傳回正確的指標值,例如 func() X { return &sync.Mutex{} }.
以上是## 如何在 Go 中使用具體類型初始化介面切片?的詳細內容。更多資訊請關注PHP中文網其他相關文章!