Go泛型編程庫:gen

jopen 10年前發布 | 22K 次閱讀 Google Go/Golang開發 Go

gen 項目目的是為 Go 語言帶來了類似泛型的函數,靈感來自 C# 的 LinQ 和 JavaScript 的 Array methods 以及 underscore 庫。操作包括過濾、分組、排序等等。

Where

Returns a new slice (plural type) whose elements return true for passed func. Comparable to Linq’s Where and JavaScript’s filter.

func (rcv Things) Where(fn func(*Thing) bool) Things

Example:

shiny := func(p *Product) bool {
    return p.Manufacturer == "Apple"
}
wishlist := products.Where(shiny)

Count

Returns an int representing the number of elements which return true for passed func. Comparable to Linq’s Count.

func (rcv Things) Count(fn func(*Thing) bool) int

Example:

countDracula := monsters.Count(func(m *Monster) bool {
    return m.HasFangs()
})

Any

Returns true if one or more elements returns true for passed func. Comparable to Linq’s Any or underscore’s some.

func (rcv Things) Any(fn func(*Thing) bool) bool

Example:

bueller := func(s *Student) bool {
    return s.IsTruant
}
willBeHijinks := students.Any(bueller)

All

Returns true if every element returns true for passed func. Comparable to Linq’s All or underscore’s every.

func (rcv Things) All(fn func(*Thing) bool) bool

Example:

mustPass := func(t *Thing) bool {
    return !t.IsEternal
}
cliché := things.All(mustPass)

First

Returns first element which returns true for passed func. Comparable to Linq’s First or underscore’s find.

func (rcv Things) First(fn func(*Thing) bool) (*Thing, error)

Example:

come := func(c *Customer) bool {
    return c.IsHere
}
served, err := people.First(come)

Returns error if no elements satisfy the func.

Single

Returns unique element which returns true for passed func. Comparable to Linq’s Single.

func (rcv Things) Single(fn func(*Thing) bool) (*Thing, error)

Example:

id := request.Id
byId := func(t *Thing) bool {
    return t.Id == id
}
item, err := things.Single(byId)

Returns error if multiple or no elements satisfy the func.

Each

Invokes passed func on every element. Comparable to underscore’s each.

func (rcv Things) Each(fn func(*Thing))

Example:

update := func(s *Score) {
    s.Recalc()
}
scores.Each(update)

Sort

Returns a new slice (plural type) whose elements are sorted based on a func defining ‘less’. The less func takes two elements, and returns true if the first element is less than the second element.

func (rcv Things) Sort(less func(*Thing, *Thing) bool) Things

Example:

byRank := func(a, b *Player) bool {
    return a.Rank < b.Rank
}
leaderboard := player.Sort(byRank)

SortDesc works similarly, returning the elements in reverse order. Its implementation negates ‘less’, so is effectively Sort(equalOrGreater).

IsSorted(Desc) uses a similar idiom, returning true if the elements are sorted according to the ‘less’ comparer.

Distinct

Returns a new slice (plural type) representing unique elements. Comparable to Linq’s Distinct or underscore’s uniq.

func (rcv Things) Distinct() Things

Example:

snowflakes := hipsters.Distinct()

Keep in mind that pointers and values have different notions of equality, and therefore distinctness.

DistinctBy

Returns a new slice (plural type) representing unique elements, where equality is defined by a passed func.

func (rcv Things) DistinctBy(func(*Thing, *Thing) bool) Things

Example:

hairstyle := func(a *Fashionista, b *Fashionista) bool {
    a.Hairstyle == b.Hairstyle
}
trendsetters := fashionistas.DistinctBy(hairstyle)

Min

func (rcv Things) Min(less func(*Thing, *Thing) bool) (*Thing, error)

Returns the element containing the minimum value, when compared to other elements using a passed func defining ‘less’. Returns an error when invoked on an empty slice, considered an invalid operation.

Example:

byPrice := func(a, b *Product) bool {
    return a.Price < b.Price
}
cheapest, err := products.Min(byPrice)

In the case of multiple items being equally minimal, the first such element is returned.

Max

func (rcv Things) Max(less func(*Thing, *Thing) bool) (*Thing, error)

Returns the element containing the maximum value, when compared to other elements using a passed func defining ‘less’. Returns an error when invoked on an empty slice, considered an invalid operation.

Example:

byArea := func(a, b *House) bool {
    return a.Area() < b.Area()
}
roomiest, err := houses.Max(byArea)

Subsetting

By default, all of the above standard methods are created when you gen a type. If you would prefer only to generate specific methods, you can include a specially-formatted “tag” comment, which follows the convention of struct tags.

// gen:"Count,Where,Sort"
type Thing struct {
    Name  string
    Year  int  
    Sales float64
}

Give the comment its own line adjacent to the type defintion as you would with (or in addition to) godocs, and avoid spaces.

(Note: previous versions of gen put the comment within the type definition.)

Custom methods

Note: Custom methods are likely to be deprecated in favor of more-flexible “projection methods”. See this GitHub issue for details.

Custom methods use struct tags to project fields of a struct.

Given an example type:

type Thing struct {
    Name  string  `gen:"Select,Aggregate"`
    Year  int     `gen:"GroupBy,Select,Min"`
    Sales float64 `gen:"Sum,Max,Average"`
}

You can infer the format from above. (Avoid spaces between methods.)

Below, {{Name}} and {{Type}} represent the name and type of a tagged field. The actual name will be substituted when you gen.

Select

func (rcv Things) Select{{Name}}() []string

Returns a slice of a specific field. Comparable to Linq’s Select or underscore’s pluck.

Example:

names := myThings.SelectName() // => ["Thing One", "Thing Two"]

GroupBy

func (rcv Things) GroupBy{{Name}}() map[{{Type}}]Things

Groups elements into a map keyed by the tagged field’s value. Comparable to Linq’s GroupBy or underscore’s groupBy.

Example:

report := myThings.GroupByYear() // => { 1995: ['Thing One', 'Thing Two'], 2007: ['Thing Three', 'Thing Four'] }

Sum

func (rcv Things) Sum{{Name}}() {{Type}}

Sums a field over all elements of Things. Comparable to Linq’s Sum.

Example:

revenue := myThings.SumSales() // => 68885.74

Average

func (rcv Things) Average{{Name}}() {{Type}}

Sums a field over all elements and divides by len(Things). Comparable to Linq’s Average.

Example:

avg := myThings.AverageSales() // => 30005.74

Max

func (rcv Things) Max{{Name}}() {{Type}}

Selects the largest value of a field in Things. Comparable to Linq’s Max.

Example:

bigmoney := myThings.MaxSales() // => 685698.99

Min

func (rcv Things) Min{{Name}}() {{Type}}

Selects the least value of a field in Things. Comparable to Linq’s Min.

Example:

earliest := myThings.MinYear() // => 1995

Aggregate

func (rcv Things) Aggregate{{Name}}(fn func({{Type}}, {{Type}}) {{Type}}) {{Type}}

Iterates over Things, operating on each element while maintaining ‘state’. Comparable to Linq’s Aggregate or underscore’s reduce.

Example:

var join = func(state string, value string) string {
    if state != "" {
        state += ", "
    }
    return state + value
}
list := myThings.AggregateName(join) // => "Title One, Title Two, etc"

Go泛型編程庫:gen

項目主頁:http://www.baiduhome.net/lib/view/home/1389580392476

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!