Skip to content
All projectsOpen-source library

Godash

A generics-powered utility library that makes everyday Go code shorter, safer, and more expressive.

Role

Core contributor — team of 3 (open source)

Stack

Go, Generics, Unit testing, Go modules

Language

Go

Repository

Link pending

Problem

Go's standard library is intentionally minimal, which pushes teams to re-implement the same slice, map, and validation helpers in every repository. Before generics, doing this either required reflection (slow, unsafe) or code duplication across types.

Solution

Godash is a Go library of generic utility functions — collections, predicates, transformations, and functional helpers — designed to reduce boilerplate while keeping code statically typed and allocation-friendly.

My contribution

Implemented core utility functions in Golang as part of a 3-person open-source contributor team (Mar–Oct 2022).

Architecture

A flat, convention-driven API organized by domain (slices, maps, strings, numerics), where every function is a pure, generic function over typed constraints. No interfaces to implement, no runtime magic — just constrained functions the compiler fully checks.

Godash API surface
┌──────────────────────── Go module: godash ───────────────────────┐
│                                                                  │
│   slices ── Map · Filter · Reduce · GroupBy · Unique · Contains  │
│                                                                  │
│   maps ──── Keys · Values · Merge · Invert · Pick                │
│                                                                  │
│   strings── Split · TrimAll · Capitalize · Truncate              │
│                                                                  │
│   predicates── Any · All · None        (pure, generic, tested)   │
└──────────────────────────────────────────────────────────────────┘

Overview

Godash started as the utility code I kept copying between Go projects: slice filtering, map transformations, grouping, deduplication, safe lookups, and small functional helpers. Copying it meant keeping several versions in sync; reflection-based alternatives meant giving up type safety and paying a runtime cost.

Go generics made a proper utility library viable for the first time, so I extracted, generalized, and hardened those helpers into a single module.

Requirements

The library had to be:

  • Fully generic — one implementation per helper, checked at compile time for every element type.
  • Allocation-conscious — helpers should not silently allocate more than necessary.
  • Predictable in behavior — pure functions, no hidden state, no panics on empty input.
  • Small and focused per function, so individual helpers stay obvious at a glance.
  • Covered by tests for the common cases and the edge cases (empty, nil, single-element).

Technical Decisions

The main design tension in a Go generics utility library is between flexibility and call-site readability. Pushing too many type parameters into signatures makes functions powerful but unreadable; too few makes them useless.

I resolved this by giving each helper the minimum parameter set it genuinely needs, using constraints for element types and separate type parameters only when input and output types differ — as in Map and Fold. Functions that would have required awkward multi-type signatures were split into two simpler, composable helpers instead.

Naming follows a strict convention (verbs for transformations, `Any`/`All` for predicates, `By` suffix for key-based variants), so the API surface becomes self-describing.

Challenges

Edge cases around nil slices and nil maps required deliberate decisions: every helper treats nil as an empty collection rather than panicking, which matches how calling code actually behaves in practice.

Keeping generic constraints readable meant centralizing common constraints so function signatures stay short and consistent.

Results

A cohesive utility module that removes repeated boilerplate from my Go codebases and serves as a personal reference implementation for Go generics in practice.

The hard part

Expressing flexible helper signatures in Go's type system without sacrificing ergonomics — for example, generic mapping with a different output type, or reduction with accumulator types — while keeping call sites clean.

A decision worth noting

Chose pure functions with constrained generics instead of a reflection-based API. This makes misuse a compile-time error rather than a runtime panic and keeps performance predictable.

Outcome

Used as the shared utility foundation across my Go projects, replacing duplicated helper packages with a single tested dependency.

Next project

Kanban