第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Go 泛型是否允許 LINQ to Objects 等效?

Go 泛型是否允許 LINQ to Objects 等效?

Go
嗶嗶one 2022-11-23 13:57:36
隨著Go 1.18 中泛型的加入,現(xiàn)在是否有可能提出與 C# 的LINQ to Objects等效的東西?還是與 C# 泛型相比,Go 的泛型在原則上缺乏某些東西,這會使它變得困難或不可能?例如,最初的101 個 LINQ 示例(“LowNumbers”)中的第一個現(xiàn)在可以使用泛型在 Go 中實現(xiàn),大致如下所示:package mainimport (    "fmt")type collection[T comparable] []Tfunc (input collection[T]) where(pred func(T) bool) collection[T] {    result := collection[T]{}    for _, j := range input {        if pred(j) {            result = append(result, j)        }    }    return result}func main() {    numbers := collection[int]{5, 4, 1, 3, 9, 8, 6, 7, 2, 0}    lowNums := numbers.where(func(i int) bool { return i < 5 })    fmt.Println("Numbers < 5:")    fmt.Println(lowNums)}
查看完整描述

2 回答

?
米脂

TA貢獻1836條經(jīng)驗 獲得超3個贊

是和不是。

幾乎可以使用鏈式 API 到達那里。這適用于許多標準 LINQ 方法,例如Skip、Take、Where、FirstLast。

不起作用的是,當您需要切換到流/流中的另一種通用類型時。

Go 泛型不允許方法具有除定義它們的接口/結構之外的其他類型參數(shù)。例如,你不能有一個結構Foo[T any],然后有一個方法Bar[O any] 這是方法所必需的,比如Select你有一種類型的輸入和另一種類型的輸出。

但是,如果您不使用鏈接而只是使用普通函數(shù)。那么您可以獲得非常接近的功能。

我已經(jīng)在這里完成了:https ://github.com/asynkron/gofun

這是一個通過模擬協(xié)程實現(xiàn)的完全懶惰的可枚舉實現(xiàn)。

在這里不起作用的是Zip需要同時枚舉兩個可枚舉的函數(shù)。(雖然有辦法破解它。但沒什么好看的)


查看完整回答
反對 回復 2022-11-23
?
忽然笑

TA貢獻1806條經(jīng)驗 獲得超5個贊

Go 的參數(shù)多態(tài)性與 C# 或 Java 中的泛型實現(xiàn)之間的一個顯著區(qū)別是 Go(仍然)沒有針對類型參數(shù)的協(xié)方差/反方差的語法。

例如,在 C# 中,您可以擁有實現(xiàn)IComparer<T>和傳遞派生容器類的代碼;或者在 Java 中典型Predicate<? super T>的流 API。在 Go 中,類型必須完全匹配,并且使用不同的類型參數(shù)實例化泛型類型會產生不同的命名類型,這些類型不能相互分配。另請參閱:為什么 Go 不允許將一個泛型分配給另一個泛型?

Go 也不是 OO,所以沒有繼承的概念。您可能有實現(xiàn)接口的類型,甚至是參數(shù)化接口。一個人為的例子:

type Equaler[T any] interface {

    Equals(T) bool

}


type Vector []int32


func (v Vector) Equals(other Vector) bool {

    // some logic

}

因此,使用這段代碼,實現(xiàn)Vector了一個特定Equaler的實例。Equaler[Vector]需要明確的是,以下 var 聲明可以編譯:


var _ Equaler[Vector] = Vector{}

因此,有了這個,您可以編寫通用的函數(shù)T并用于T實例化Equaler,并且您將能夠傳遞任何實現(xiàn)該特定實例的東西Equaler:


func Remove[E Equaler[T], T any](es []E, v T) []E {

    for i, e := range es {

        if e.Equals(v) {

            return append(es[:i], es[i+1:]...)

        }

    }

    return es

}

您可以使用 any 調用此函數(shù)T,因此使用T具有Equals(T)方法的 any :


// some other random type that implements Equaler[T]

type MyString string


// implements Equaler[string]

func (s MyString) Equals(other string) bool {

    return strings.Split(string(s), "-")[0] == other

}


func main() {

    vecs := []Vector{{1, 2}, {3, 4, 5}, {6, 7}, {8}}

    fmt.Println(Remove(vecs, Vector{6, 7})) 

    // prints [[1 2] [3 4 5] [8]]


    strs := []MyString{"foo-bar", "hello-world", "bar-baz"}

    fmt.Println(Remove(strs, "hello"))

    // prints [foo-bar bar-baz]

}

唯一的問題是只有定義的類型才能有方法,所以這種方法已經(jīng)排除了所有復合的非命名類型。


然而,為了部分挽救,Go 具有高階函數(shù),因此使用高階函數(shù)和非命名類型編寫類似流的 API 并非不可能,例如:


func Where[C ~[]T, T any](collection C, predicate func(T) bool) (out C) {

    for _, v := range collection {

        if predicate(v) {

            out = append(out, v)

        }

    }

    return 

}


func main() {

    // vecs declared earlier

    filtered := Where(vecs, func(v Vector) bool { return v[0] == 3})

    fmt.Printf("%T %v", filtered, filtered)

    // prints []main.Vector [[3 4 5]]

}

特別是在這里你使用命名類型參數(shù)C ~[]T而不是僅僅定義collection []T,這樣你就可以將它用于命名和非命名類型。


操場上可用的代碼:https ://gotipplay.golang.org/p/mCM2TJ9qb3F


(選擇參數(shù)化接口還是高階函數(shù)可能取決于,除其他外,如果你想鏈接方法,但 Go 中的方法鏈接一開始并不是很常見。)


結論:這是否足以模仿 LINQ 或類似 Stream 的 API,和/或啟用大型通用庫,只有實踐才能證明?,F(xiàn)有設施非常強大,在語言設計者獲得泛型實際使用的額外經(jīng)驗后,Go 1.19 中的功能可能會變得更加強大。


查看完整回答
反對 回復 2022-11-23
  • 2 回答
  • 0 關注
  • 188 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號