Shipped v2 of go-js-array-methods — JS-style Filter, Map, Reduce for Go slices

Published: (May 9, 2026 at 06:57 PM EDT)
3 min read
Source: Dev.to

Source: Dev.to

Quick taste

import "github.com/bube054/go-js-array-methods/v2/array"

nums := []int{1, 2, 3, 4, 5}

even := array.Filter(nums, func(n, _ int, _ []int) bool { return n%2 == 0 })
doubled := array.Map(even, func(n, _ int, _ []int) int { return n * 2 })
// [4, 8]

Or chainable, if you prefer that style:

arr := array.Array[int]{1, 2, 3, 4, 5}

result := arr.
    Filter(func(n, _ int, _ []int) bool { return n%2 == 0 }).
    Push(6).
    Reverse()
// [6, 4, 2]

Both styles are interchangeable. Use whichever fits the surrounding code.

What’s in it

The 30+ methods you’d actually reach for:

  • Filter, Map, Reduce (with ReduceRight and *Strict variants that preserve the input type)
  • Find, FindIndex, FindLast, FindLastIndex
  • Every, Some, Includes, IndexOf, LastIndexOf
  • At, Slice, Splice, Push, Pop, Shift, Unshift
  • Concat, Reverse, Fill, CopyWithin, Flat, ForEach, Join
  • Entries, With, ToString, ValueOf

What’s intentionally not in it

  • Sort – Go’s slices.Sort and the sort package already handle sorting well.
  • Keys – Simple for i := range slice suffices.
  • FlatMap – Planned for a future release; contributions are welcome.

A few things worth knowing

Immutable by default. Every function returns a new slice; the input never changes, even for “mutating” methods like Push or Splice. This avoids aliasing bugs.

Negative indexes. At(-1) returns the last element. Slice(s, -2, -1) works like JavaScript. Out‑of‑range access returns an error instead of panicking.

Map is properly generic. The compiler infers the output type from your callback, keeping call sites clean:

nums := []int{1, 2, 3}
strs := array.Map(nums, func(n, _ int, _ []int) string {
    return fmt.Sprintf("#%d", n)
})
// []string{"#1", "#2", "#3"} – no type assertions, no []any

If you want the output type locked to the input type, use MapStrict.

Go quirk. Go does not allow type parameters on methods, only on functions. Therefore Array[T].Map() is limited to Array[any]. For a fully type‑safe Map, use the array.Map function directly; the chainable style works for the other methods.

A couple of patterns I find myself using

Sum a slice without a manual accumulator

nums := []int{1, 2, 3, 4}
initial := 0
sum, _ := array.ReduceStrict(nums, func(acc, n, _ int, _ []int) int {
    return acc + n
}, &initial)
// sum == 10

Flatten a mixed nested slice

nested := []any{1, []int{2, 3}, []int{4, 5}}
flat, _ := array.Flat[int](nested)
// []int{1, 2, 3, 4, 5}

Transform a slice of strings while preserving type safety

arr := array.Array[string]{"alice", "bob", "carol"}
shouts := arr.MapStrict(func(s string, _ int, _ []string) string {
    return strings.ToUpper(s) + "!"
})
// [ALICE! BOB! CAROL!]

More runnable examples with output are available in array/example_test.go and on pkg.go.dev.

If this is useful to you

A star on the repository is a helpful signal that guides which projects I continue to maintain. Most Go developers don’t discover this library on their own and end up writing manual loops.

If you know someone who misses filter/map in Go, sharing this library is a real favor. Issues reporting missing methods or edge cases are valuable—especially when you can point to the expected JavaScript behavior. Pull requests are also welcome.

0 views
Back to Blog

Related posts

Read more »

Bun ported to Rust in 6 days

Overview - Test coverage: 99.8 % of Bun’s pre‑existing test suite passes on Linux x64 glibc in the Rust rewrite. - The codebase is essentially the same, but Ru...