首頁 >後端開發 >Golang >進一步約束Golang中的型別參數(使用Contains方法實作泛型List)

進一步約束Golang中的型別參數(使用Contains方法實作泛型List)

WBOY
WBOY轉載
2024-02-06 08:15:04582瀏覽

進一步約束Golang中的型別參數(使用Contains方法實作泛型List)

問題內容

假設我想寫一個通用的list 類型,其中包含一些有用的方法,例如:

type list[t any] []t

func (l *list[t]) len() int
func (l *list[t]) get(pos int) (t t, err error)
func (l *list[t]) set(pos int, t t) error
func (l *list[t]) append(t ...t)
func (l *list[t]) insert(t t, pos int) error
func (l *list[t]) remove(pos int) (t t, err error)
// etc...

但是,還有其他有用的方法可能需要進一步限制清單的元素類型 t。例如,我們無法在此 list 類型上實作 contains 方法:

func (l *list[t]) contains(t t) bool {
    for _, s := range *l {
        if s == t { // compiler error: invalid operation: s == t (incomparable types in type set)
            return true
        }
    }
    return false
}

如果我們宣告 list 為,我們只能實作 contains

#
type List[T comparable] []T

但這使得不可能建立不可比較類型的 list

有沒有辦法可以兩全其美?即有一個可用於不可比較類型tlist[t] ,但在t 具有可比性的情況下允許它有一個contains 方法?

我想到了:

  • 使用不同類型(例如 uncomparablelist/listlist/comparablelist
  • 使 包含 為函數而不是方法

但我不太喜歡其中任何一個。


正確答案


go 沒有專門化,所以我認為你不能讓它完全像這樣工作(儘管不是泛型專家)。

我認為解決此問題的一種合理的 go 方式是傳遞一個顯式比較器:

func (l *list[t]) contains(t t, cmp func(t, t) bool) bool {
    for _, s := range *l {
        if cmp(s, t) {
            return true
        }
    }
    return false
}

然後你就可以了

func main() {
    list := list[int]([]int{1,2,3})
    fmt.println(list.contains(2, func(a, b int) bool { return a == b })) // true
}

對於類似的類型,您可以提供預設值:

func eq[t comparable](a, b t) bool {
    return a == b
}

所以上面變成了

func main() {
    list := List[int]([]int{1,2,3})
    fmt.Println(list.Contains(2, Eq[int]) // true
}

您也可以在list 類型中嵌入一個比較器,並為其指定預設值func(a, b t) bool { return false } 並公開一個可以將自定義比較器傳遞到其中的建構函式。但這可能對您來說太隱晦了。

以上是進一步約束Golang中的型別參數(使用Contains方法實作泛型List)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除