首頁  >  文章  >  後端開發  >  如何使用 Golang 泛型和介面用具體實作填滿切片?

如何使用 Golang 泛型和介面用具體實作填滿切片?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-10-26 10:33:02704瀏覽

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 Y 為any 則刪除了介面與其特定實作之間的關係。在編譯時,只知道 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 值而不是所需具體類型的實例。

更好的方法是使用建構函數而不是第二個泛型參數,如下所示:

<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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn