Gofu is a Go 1.27+ generic collections library providing fluent, type-safe functional data transformations for slices and maps — Map, Filter, Reduce, FlatMap, GroupBy, Partition, SortBy, and more. It provides the same API for sequential (Slice) and parallel (ParallelSlice) code. Zero reflection or interface{}.
go build ./...— build all packagesgo test ./... -v -count=1— run all unit tests (root + test/)go vet ./...— vetgolangci-lint run ./...— lintgo run ./examples/slice/main.go— run slice examplego run ./examples/map/main.go— run map examplego run ./examples/starwars/main.go— run starwars example (SWAPI)go run ./examples/rickandmorty/main.go— run rickandmorty example (R&M API)
slice.go,map.go— type definitions (Slice[T],Map[K,V],Entry[K,V],ParallelSlice[T])*_read.go— read-only queries (Count,First,Find,ContainsFunc)*_transform.go— immutable transforms (Map,Filter,Reduce,GroupBy)*_mut.go— in-place mutation (Delete,Reverse,Compact,Shuffle,Filter)*_loop.go— chunk-based helpers (MapChunks)parallel_slice*.go— concurrent slice operationsmap_join.go— set ops (Merge,Intersect,Difference)test/slice/,test/map/— unit tests (one file per method)examples/slice/,examples/map/— runnable examples
- Formatter: gofumpt + gci (
golangci-lint run --fix) - Go 1.27: generic methods on generic types. No reflection/
interface{}. - No interfaces: return concrete types (
Slice[T],ParallelSlice[T]). - Value receivers on all methods.
- Immutability: methods return new collections. Opt-in mutation via
.Mut(). - Sharing allowed: some methods share backing arrays. Call
Copy()for independence. - Type inference: prefer inferred over explicit type params.
- Doc comments: methods use
// Name description. [ Immutable | Mutates | ReadOnly ] [ time: O(...); space: O(...) ]— short sentence, then blank line, then detail. No implementation details. No unexported refs. Types must NOT carry[IMMUTABLE|MUTATES|READONLY]tags. - No em dashes: use ASCII
-. - Tests: data-driven table tests. See tests.md for rules. Use
assert.Eq/assert.EqSlicefromtest/assert/. - Mutation methods (in-place):
.Reverse(),.Delete(),.Compact(),.Shuffle(). For Slice/Map:.Mut().Filter()returns original type. Map also has.Mut().Delete(key)and.Mut().DeleteFunc(pred). - Generic instantiation cycles: always wrap public method results in
Map/Sliceconstructors. Use direct slice indexing where possible.
- Generic methods first (
Map[R],FlatMap[R],Reduce[R],ToMap[K,V],GroupBy[K],DistinctBy[K],IndexBy[K],MapChunks[R],ToSlice[S]) - Non-generic transforms (
Filter,Partition) - Mut-counterparts at bottom (
Reverse,SortBy,Shuffle) - Least logic last (
Copy,Collect) - Group by naming (
Map/FlatMap/ToMap,First/FirstOr,Merge/Intersect,Keys/Values)
- No reflection or
interface{} - Don't call unexported helpers (
mapNoAlloc,collectMapResults,shouldSequential) - Don't mix MUTATES and IMMUTABLE —
Copy()first if you need the original after mutation - Don't commit unless asked
Map.Difference:maps.Clone+deleteloop (faster at low/moderate overlap vs insert-only; insert-only only wins at 90%+ overlap).- No interfaces: Go 1.27 doesn't support type params on interface methods, so return concrete types for full chaining without type assertions.