Go泛型编程库:gen
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"