go2linq is a Go implementation of .NET’s
LINQ to Objects.
It brings the familiar LINQ query operators — Where, Select, GroupBy,
Join, OrderBy, Aggregate and dozens more — to Go, implemented as generic
functions over sequences.
See also: Language Integrated Query, LINQ, Enumerable Class.
v4 of go2linq is built on Go’s standard
iterators: a sequence is simply an
iter.Seq[T]. Because operators consume and
produce plain iter.Seq values, go2linq composes naturally with the standard
library (slices,
maps) and with any other code that speaks the
iter.Seq protocol — no custom collection type is required.
package main
import (
"fmt"
"github.com/solsw/go2linq/v4"
"github.com/solsw/iterhelper"
)
func main() {
filter, _ := go2linq.Where(
iterhelper.Var(1, 2, 3, 4, 5, 6, 7, 8),
func(i int) bool { return i > 6 || i%2 == 0 },
)
squares, _ := go2linq.Select(
filter,
func(i int) string { return fmt.Sprintf("%d: %d", i, i*i) },
)
for square := range squares {
fmt.Println(square)
}
}
Output:
2: 4
4: 16
6: 36
7: 49
8: 64
go get github.com/solsw/go2linq/v4
import "github.com/solsw/go2linq/v4"
Requires Go 1.26 or later (for iterator support).
Each operator returns (result, error) rather than panicking. The error is
non-nil when an argument is invalid — a nil source, or a nil
predicate/selector/comparison function — and for operators that can fail at
evaluation time (e.g. Single on a sequence with more than one element, or
ElementAt with an out-of-range index). All error values are exported from the
package (see Errors), so they can be matched with errors.Is.
Following LINQ semantics, operators fall into two groups:
Where, Select, Concat, OrderBy, …) return a
new iter.Seq[T] and do no work until the result is ranged over. They can be
chained freely; nothing is materialized until you iterate.Count, First, Aggregate, ToMap,
SequenceEqual, …) consume the source and return a final value right away.go2linq exposes a base operator plus suffixed variants. The suffixes signal what extra argument the variant takes:
| Suffix | Meaning | Example |
|---|---|---|
Idx |
the element’s index is passed to the predicate/selector | WhereIdx, SelectIdx |
Pred |
takes a predicate to filter which elements qualify | FirstPred, CountPred |
Sel |
takes a selector that projects each element | AverageSel, MaxSel |
By |
groups/compares elements by a key selector | DistinctBy, ExceptBy |
Res |
takes a result selector to shape the output | GroupByRes |
Eq |
takes an equality function func(T, T) bool |
DistinctEq, ContainsEq |
Cmp |
takes a comparison function func(T, T) int |
DistinctCmp, UnionCmp |
Ls |
takes a “less” function func(T, T) bool |
OrderByLs, MaxLs |
Def |
takes an explicit default value | DefaultIfEmptyDef |
Operators without an Eq/Cmp/Ls suffix use Go’s built-in comparison
(comparable / cmp.Ordered) where one is required.
Where, WhereIdx, OfType, Cast
Select, SelectIdx, SelectMany, SelectManyIdx, SelectManyColl,
SelectManyCollIdx, Zip
Skip, SkipLast, SkipWhile, SkipWhileIdx,
Take, TakeLast, TakeWhile, TakeWhileIdx, Chunk
Concat, ConcatMany, Append, Prepend
OrderBy, OrderByLs, OrderByDesc, OrderByDescLs,
OrderByKey, OrderByKeyLs, OrderByKeyDesc, OrderByKeyDescLs,
ThenLess, Reverse, ReverseLess
GroupBy, GroupByEq, GroupBySel, GroupBySelEq,
GroupByRes, GroupByResEq, GroupBySelRes, GroupBySelResEq
Join, JoinEq, GroupJoin, GroupJoinEq
Distinct, DistinctCmp, DistinctEq, DistinctBy, DistinctByCmp, DistinctByEq,
Except, ExceptCmp, ExceptEq, ExceptBy, ExceptByCmp, ExceptByEq,
Intersect, IntersectCmp, IntersectEq, IntersectBy, IntersectByCmp, IntersectByEq,
Union, UnionCmp, UnionEq, UnionBy, UnionByCmp, UnionByEq
Aggregate, AggregateSeed, AggregateSeedSel,
AggregateBy, AggregateByEq, AggregateBySel, AggregateBySelEq,
Average, AverageSel, Sum, SumSel,
Count, CountPred, CountBy, CountByEq,
Max, MaxLs, MaxSel, MaxSelLs, MaxBySel, MaxBySelLs,
Min, MinLs, MinSel, MinSelLs, MinBySel, MinBySelLs
All, Any, AnyPred, Contains, ContainsEq, SequenceEqual, SequenceEqualEq
First, FirstPred, FirstOrDefault, FirstOrDefaultPred,
Last, LastPred, LastOrDefault, LastOrDefaultPred,
Single, SinglePred, SingleOrDefault, SingleOrDefaultPred,
SingleOrZero, SingleOrZeroPred,
ElementAt, ElementAtOrDefault, DefaultIfEmpty, DefaultIfEmptyDef
Empty, Range, Repeat, InfiniteSequence
ToMap, ToMapSel,
ToLookup, ToLookupEq, ToLookupSel, ToLookupSelEq,
Index, ApplyResultSelector
Identity — selector that returns its argument unchanged.
For full signatures and per-operator documentation, see the Go Reference.
All errors returned by the package are exported and can be tested with
errors.Is:
| Error | Meaning |
|---|---|
ErrNilSource |
the source sequence is nil |
ErrNilPredicate |
a required predicate function is nil |
ErrNilSelector |
a required selector function is nil |
ErrNilAccumulator |
a required accumulator function is nil |
ErrNilEqual |
a required equality function is nil |
ErrNilCompare |
a required comparison function is nil |
ErrNilLess |
a required “less” function is nil |
ErrNilNext |
a required “next” function is nil |
ErrEmptySource |
the source is empty where a value is required |
ErrMultipleElements |
Single found more than one element |
ErrMultipleMatch |
SinglePred matched more than one element |
ErrNoMatch |
a predicate matched no element |
ErrIndexOutOfRange |
the requested index is out of range |
ErrNegativeCount |
a negative count was supplied |
ErrSizeOutOfRange |
a size argument (e.g. Chunk) is out of range |
ErrDuplicateKeys |
ToMap encountered duplicate keys |
Runnable examples accompany every operator as Example... functions in the test
files; they are rendered in the
package documentation.
go2linq is distributed under the terms of the LICENSE file in the repository root.