# gubrak: a lodash-shaped utility library for Go

> gubrak is a Go utility library inspired by lodash, with around seventy functions for slices, maps, strings and numbers, plus a chainable API for building pipelines. It is MIT licensed, depends only on a CSV package and testify in tests, and its v2 line was last released on 2026-05-02.

**novalagung/gubrak** — ⚙️ Golang functional utility library with syntactic sugar. It's like lodash, but for Go

- Repository: https://github.com/novalagung/gubrak
- Website: https://pkg.go.dev/github.com/novalagung/gubrak/v2
- Stars: 519 · Forks: 41
- Language: Go
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/novalagung-gubrak

## What the library is trying to be

gubrak describes itself as a lodash-inspired functional utility library for Go, and the repository description puts it more bluntly: a Golang functional utility library with syntactic sugar, it's like lodash but for Go.

The gap it fills is real and familiar to anyone who has written JavaScript. JavaScript's arrays and objects are dynamic, so lodash grew a large collection of operations that treat a collection as a value you can chain. Go's slices and maps are typed, and the standard library until recently gave you almost nothing above append and sort. gubrak was written to supply that layer.

The scale is visible in the API list, which runs to around seventy functions covering collection operations, type checks, string and number helpers and a few odds and ends. The collection side includes Chunk, Compact, Concat, Count, Difference, Drop, DropRight, Each, EachRight, Fill, Filter, Find, FindIndex, FindLast, FindLastIndex, First, ForEach, ForEachRight, FromPairs, GroupBy, Head, Includes, IndexOf, Initial, Intersection, Join, KeyBy, Last, LastIndexOf, Map, Nth, OrderBy, Partition, Pull, PullAll, PullAt, Reduce, Reject, Remove, Reverse, Sample, SampleSize, Shuffle, Size, SortBy, Tail, Take, TakeRight, Union, Uniq and Without.

The type-check side is unusually complete for a Go library: IsArray, IsBool, IsChannel, IsDate, IsEmpty, IsEmptyString, IsFloat, IsFunction, IsInt, IsMap, IsNil, IsNumeric, IsPointer, IsSlice, IsString, IsStructObject, IsTrue, IsUint and IsZeroNumber. The string and number side adds Now, RandomInt, RandomString and a set of operation_string and operation_number helpers.

The licence is MIT and the homepage is the pkg.go.dev page for the module.

## Installing it and the module path

Installation is the standard go get:

```bash
go get -u github.com/novalagung/gubrak/v2
```

Note the /v2 suffix on the import path. That is Go's semantic import versioning, which means the v2 line lives at a different import path from v1 rather than in a subdirectory, and it is the thing most likely to trip up a new user who copies an older example. The go.mod confirms the module path is github.com/novalagung/gubrak/v2.

The dependency situation is unusually clean for a library of this type. The go.mod requires github.com/gocarina/gocsv at a pseudo-version and github.com/stretchr/testify at v1.10.0, and the indirect block is just davecgh/go-spew, pmezard/go-difflib and gopkg.in/yaml.v3, which are testify's own dependencies. So a library with no runtime dependencies of its own beyond a CSV reader, and a test framework for its own tests.

The declared Go version is 1.18, which is the version that introduced generics and is therefore the natural floor for a library offering generic collection helpers. That is a sensible choice: it keeps the module usable on any Go release from 1.18 onwards.

The documentation lives on pkg.go.dev rather than in the repository, and the README links the module page and shows a Hello World example as an image rather than as text, which is a small piece of evidence about how the project presents itself.

## The chainable API and how the files are organised

The most substantial part of the library is the chainable API, and the repository layout shows how it is built. There are five chainable files: operation_chainable_helper.go, operation_chainable_implementation.go, operation_chainable_interface.go, and then a family of result types split by return signature, operation_chainable_interface_result_for_bool.go, for_no_return_value.go, for_number.go, for_string.go and for_two_return_value.go.

That split is the interesting design decision. A chain in lodash ends in a value, and lodash achieves this with a single chain wrapper whose final call is dispatched on the method name at runtime. Splitting the result types into separate files by return signature means the compiler can pick the right chain type at the point the method is called, which is what makes a statically typed chain possible at all in Go.

The non-chainable side is split by domain: operation_is.go for the type predicates, operation_number.go for the numeric helpers, operation_string.go for the string helpers, plus operation_chainable_helper.go and operation_chainable_implementation.go for the chain plumbing.

The repository root is flat, with one file per concern and no internal package directories, and every operation file has a matching example test and a test file, for example operation_is_example_test.go and operation_is_test.go, and the same pattern for operation_number, operation_string and the chainable implementation. There is also a performance_test.go at the root, which tells you the project benchmarks its own operations.

The coverage.json file at the root is what the coverage badge in the README reads, so the coverage number shown on the repository is generated rather than typed in.

## Testing, and what the test command tells you

The README documents a single test command:

```bash
go test -count=1 -race -run "^Test" -skip "TestLoadData" . -v --cover
```

Each flag is doing something specific, and together they describe how the project wants its tests run.

-count=1 disables Go's test caching, so a run always executes the tests rather than replaying a cached result. The -race flag enables the race detector, which for a library with concurrent collection helpers is not optional; a data race in a helper that several goroutines call is the kind of bug that would otherwise surface in a user's program. -run "^Test" selects test functions by name. -skip "TestLoadData" excludes one test by name, and the name suggests it loads a data file, which is the kind of test that needs a fixture on disk and is excluded when running in an environment that does not have it. The -v flag makes the output verbose and --cover turns on coverage reporting.

The Contribution section is a one-liner: Fork, Create branch, Commit, Push, Pull Requests. There is no CODE_OF_CONDUCT, no separate contributing guide and no detailed style rules in the repository entries, which tells you the contribution expectations are light.

The .github directory holds the workflows, and the badges in the README point at a build status workflow and the coverage endpoint, both of which read from files in the repository rather than from an external service.

## Where gubrak is the wrong choice

Three limits are structural. The first is the standard library gap that no longer exists in the way the library was written for. gubrak was created when Go had no generics and the only option for a generic map or filter was reflection or code generation. Go 1.21 added the slices and maps packages to the standard library, and slices.Sorted, slices.Contains, slices.Index, slices.Collect and the maps package cover a meaningful part of what gubrak does with type safety and no dependency. The difference in approach is that gubrak offers a uniform lodash-style surface across many types including maps and strings, while the standard library gives you narrower, more focused functions per package.

The second is that it is a subset, not a port. gubrak covers around seventy operations, but lodash has several hundred and a semantics that JavaScript's dynamic types make easy. Every gubrak function has to pick a Go-idiomatic answer to a question lodash can leave ambiguous, and those answers differ from lodash in places, which is the usual source of surprise when a developer arrives from JavaScript. The type predicates are a good example of the difference: IsArray, IsMap and IsSlice cannot behave the way lodash's isArray and isObject do, because Go's type system makes the distinctions explicit.

The third is the maintenance state. The releases are v2.0.3 on 2026-05-02, v2.0.2 on 2025-08-20 and v2.0.1 on 2020-05-26, so there was a five-year gap between the second and third of those, and the last push was on 2026-05-02, more than five months before today. For a small utility library that is a manageable risk rather than a serious one, since the code is short and MIT licensed, but it does mean an unversioned dependency on a patch that will not arrive from upstream.

There is also a question of whether a utility library is what you want at all. A large collection of small helpers creates an implicit dependency on a particular style, and a codebase that reaches for gubrak everywhere is a codebase where every future reader has to know it. Using it for a handful of operations in one place is a different proposition from standardising on it.

## Conclusion

gubrak suits a Go developer who likes the lodash vocabulary and wants the same operations without hand-writing them, especially where the standard library's generics-based slices package is awkward to chain. It is the wrong tool if you would rather build on the standard library, since Go 1.21 onward has slices and maps packages that cover a good part of this surface, and it is the wrong tool if you need the full lodash semantics, because gubrak is a subset with Go-specific differences. Verify first which of the roughly seventy functions you would actually call, and note that the module path carries a v2 suffix while the go.mod requires Go 1.18 and the last push was on 2026-05-02.

## FAQ

### What is gubrak?

It is a lodash-inspired functional utility library for Go, providing around seventy functions for slices, maps, strings and numbers along with a chainable API. It is MIT licensed and its documentation is on pkg.go.dev.

### How do I install gubrak?

Run go get -u github.com/novalagung/gubrak/v2. Note the v2 suffix on the import path, which is Go's semantic import versioning, so v2 lives at a different import path from v1.

### Does gubrak have any runtime dependencies?

Very few. The go.mod requires github.com/gocarina/gocsv at a pseudo-version and github.com/stretchr/testify for tests, with only testify's own indirect dependencies below that. The module declares Go 1.18 as its minimum.

### How does the gubrak chainable API work in a typed language?

The chain result types are split into separate files by return signature, one each for bool, no return value, number, string and two return values, so the compiler picks the right chain type at the call site rather than dispatching on a method name at runtime as lodash does.

### What kinds of helpers does gubrak provide beyond collections?

A full set of type predicates including IsArray, IsBool, IsChannel, IsDate, IsEmpty, IsEmptyString, IsFloat, IsFunction, IsInt, IsMap, IsNil, IsNumeric, IsPointer, IsSlice, IsString, IsStructObject, IsTrue, IsUint and IsZeroNumber, plus string and number helpers such as Now, RandomInt and RandomString.

### How do I run the gubrak tests?

The README gives go test -count=1 -race -run "^Test" -skip "TestLoadData" . -v --cover, which disables the test cache, enables the race detector and skips the fixture-loading test, with verbose output and coverage.

## Sources

- [License: MIT](https://github.com/novalagung/gubrak/blob/master/LICENSE)
- [novalagung/gubrak on GitHub](https://github.com/novalagung/gubrak)
- [Project website](https://pkg.go.dev/github.com/novalagung/gubrak/v2)
- [README](https://github.com/novalagung/gubrak/blob/master/README.md)
- [Releases](https://github.com/novalagung/gubrak/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/novalagung-gubrak
