# go-linq **Repository Path**: mirrors/go-linq ## Basic Information - **Project Name**: go-linq - **Description**: .NET LINQ capabilities in Go - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2017-04-03 - **Last Updated**: 2025-11-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # go-linq [![GoDoc](https://godoc.org/github.com/ahmetb/go-linq?status.svg)](https://godoc.org/github.com/ahmetb/go-linq) [![Build Status](https://github.com/ahmetb/go-linq/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/ahmetb/go-linq/actions/workflows/ci.yml) [![Coverage Status](https://coveralls.io/repos/github/ahmetb/go-linq/badge.svg?branch=master)](https://coveralls.io/github/ahmetb/go-linq?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/ahmetb/go-linq)](https://goreportcard.com/report/github.com/ahmetb/go-linq) A powerful language integrated query (LINQ) library for Go. * Written in vanilla Go, no dependencies! * Complete lazy evaluation with iterator pattern * Safe for concurrent use * Supports generic functions to make your code cleaner and free of type assertions * Supports arrays, slices, maps, strings, channels and custom collections ## Installation When used with Go modules, use the following import path: go get github.com/ahmetb/go-linq/v4 Older versions of Go using different dependency management tools can use the following import path to prevent breaking API changes: go get gopkg.in/ahmetb/go-linq.v4 ## Quickstart Usage is as easy as chaining methods like: `From(slice)` `.Where(predicate)` `.Select(selector)` `.Union(data)` **Example 1: Find all owners of cars manufactured after 2015** ```go import . "github.com/ahmetb/go-linq/v4" type Car struct { year int owner, model string } ... var owners []string FromSlice(cars).Where(func(c any) bool { return c.(Car).year >= 2015 }).Select(func(c any) any { return c.(Car).owner }).ToSlice(&owners) ``` Or, you can use generic functions, like `WhereT` and `SelectT` to simplify your code (at a performance penalty): ```go var owners []string FromSlice(cars).WhereT(func(c Car) bool { return c.year >= 2015 }).SelectT(func(c Car) string { return c.owner }).ToSlice(&owners) ``` **Example 2: Find the author who has written the most books** ```go import . "github.com/ahmetb/go-linq/v4" type Book struct { id int title string authors []string } author := FromSlice(books).SelectMany( // make a flat array of authors func(book any) Query { return From(book.(Book).authors) }).GroupBy( // group by author func(author any) any { return author // author as key }, func(author any) any { return author // author as value }).OrderByDescending( // sort groups by its length func(group any) any { return len(group.(Group).Group) }).Select( // get authors out of groups func(group any) any { return group.(Group).Key }).First() // take the first author ``` **Example 3: Implement a custom method that leaves only values greater than the specified threshold** ```go type MyQuery Query func (q MyQuery) GreaterThan(threshold int) Query { return Query{ Iterate: func(yield func(any) bool) { q.Iterate(func(item any) bool { if item.(int) > threshold { return yield(item) } return true }) }, } } result := MyQuery(Range(1,10)).GreaterThan(5).Results() ``` ## Generic Functions Although Go doesn't implement generics, with some reflection tricks, you can use go-linq without typing `any`s and type assertions. This will introduce a performance penalty (5x-10x slower) but will yield in a cleaner and more readable code. Methods with `T` suffix (such as `WhereT`) accept functions with generic types. So instead of .Select(func(v any) any {...}) you can type: .SelectT(func(v YourType) YourOtherType {...}) This will make your code free of `any` and type assertions. **Example 4: "MapReduce" in a slice of string sentences to list the top 5 most used words using generic functions** ```go var results []string FromSlice(sentences). // split sentences to words SelectManyT(func(sentence string) Query { return From(strings.Split(sentence, " ")) }). // group the words GroupByT( func(word string) string { return word }, func(word string) string { return word }, ). // order by count OrderByDescendingT(func(wordGroup Group) int { return len(wordGroup.Group) }). // order by the word ThenByT(func(wordGroup Group) string { return wordGroup.Key.(string) }). Take(5). // take the top 5 // project the words using the index as rank SelectIndexedT(func(index int, wordGroup Group) string { return fmt.Sprintf("Rank: #%d, Word: %s, Counts: %d", index+1, wordGroup.Key, len(wordGroup.Group)) }). ToSlice(&results) ``` ## Manual Iteration Since **go-linq v4** manual iteration follows Go’s standard iterator pattern introduced with the `iter` package. The Query type exposes an `Iterate` field of type `iter.Seq[any]`, making it easier to integrate with Go’s native iteration style. **Example 5: Iterate over a query using the standard `for ... range` loop** ```go q := FromSlice([]int{1, 2, 3, 4}) for v := range q.Iterate { fmt.Println(v) } ``` **More examples** can be found in the [documentation](https://godoc.org/github.com/ahmetb/go-linq). ## Data Source Constructors Since **go-linq v4**, a new family of constructor functions provides a type-safe and efficient way to create queries from various data sources. Each function is optimized for its specific input type, avoiding the overhead of reflection. Available constructors: - `FromSlice` - creates a query from a slice - `FromMap` - creates a query from a map - `FromChannel` - creates a query from a channel - `FromChannelWithContext` - creates a query from a channel with `Context` support - `FromString` - creates a query from a string (iterating over runes) - `FromIterable` - creates a query from a custom collection implementing the `Iterable` interface The older `From` function remains available for backward compatibility, but it relies on runtime reflection and is significantly less efficient. For all new code, it’s recommended to use the explicit `From*` constructors. ## Release Notes ```text v4.0.0 (2025-10-12) * Breaking change: Migrated to standard Go iterator pattern. (thanks @kalaninja!) * Added typed constructors: FromSlice(), FromMap(), FromChannel(), FromChannelWithContext(), FromString(). * Breaking change: Removed FromChannelT() in favor of FromChannel(). v3.2.0 (2020-12-29) * Added FromChannelT(). * Added DefaultIfEmpty(). v3.1.0 (2019-07-09) * Support for Go modules * Added IndexOf()/IndexOfT(). v3.0.0 (2017-01-10) * Breaking change: ToSlice() now overwrites existing slice starting from index 0 and grows/reslices it as needed. * Generic methods support (thanks @cleitonmarx!) - Accepting parametrized functions was originally proposed in #26 - You can now avoid type assertions and interface{}s - Functions with generic methods are named as "MethodNameT" and signature for the existing LINQ methods are unchanged. * Added ForEach(), ForEachIndexed() and AggregateWithSeedBy(). v2.0.0 (2016-09-02) * IMPORTANT: This release is a BREAKING CHANGE. The old version is archived at the 'archive/0.9' branch or the 0.9 tags. * A COMPLETE REWRITE of go-linq with better performance and memory efficiency. (thanks @kalaninja!) * API has significantly changed. Most notably: - linq.T removed in favor of interface{} - library methods no longer return errors - PLINQ removed for now (see channels support) - support for channels, custom collections and comparables v0.9-rc4 * GroupBy() v0.9-rc3.2 * bugfix: All() iterating over values instead of indices v0.9-rc3.1 * bugfix: modifying result slice affects subsequent query methods v0.9-rc3 * removed FirstOrNil, LastOrNil, ElementAtOrNil methods v0.9-rc2.5 * slice-accepting methods accept slices of any type with reflections v0.9-rc2 * parallel linq (plinq) implemented * Queryable separated into Query & ParallelQuery * fixed early termination for All v0.9-rc1 * many linq methods are implemented * methods have error handling support * type assertion limitations are unresolved * travis-ci.org build integrated * open sourced on github, master & dev branches ```