If you've ever switched between JavaScript and Go in the same week, you've felt this. You're three lines into a Go function, you reach for .filter(), and then you remember: right, for loop. Or write a one-off helper for the third time this month.
go-js-array-methods provides Filter, Map, Reduce, Includes, At, Slice, Splice, Push, Pop — 30+ methods named exactly like their JS counterparts. Generics-powered, immutable by default, chainable if you want it.
Repo: github.com/bube054/go-js-array-methods
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'sslices.Sortand thesortpackage already handle this well. Reimplementing them just to match the JS name felt like noise. -
Keys—for i := range sliceis fine. You don't need a library for that one. -
FlatMap— on the roadmap, just not done yet. Honestly the most likely place a contribution would land cleanly.
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. JS technically mutates; this doesn't. The trade-off is you don't get aliasing bugs that show up six functions away from where the bug actually is.
Negative indexes. At(-1) gives you the last element. Slice(s, -2, -1) works the same as in JS. Out-of-range access returns an error instead of panicking.
Map is properly generic. The compiler infers the output type from your callback, so call sites stay 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 to lock the output type to the input type, there's MapStrict.
One Go quirk worth flagging. Go doesn't allow type parameters on methods, only on functions. So Array[T].Map() is locked to Array[any] and can't cleanly change the output type. If you want the full type-safe Map, use array.Map as a function directly. The chainable style still works fine for the rest.
A couple of patterns I find myself using
Sum a slice without writing 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 without leaving 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 examples (runnable, with output) live in array/example_test.go and on pkg.go.dev.
If this is useful to you
A star on the repo helps more than I'd like to admit. It's the cheap signal that tells me which projects to keep working on, and most Go devs don't stumble onto this kind of library on their own — they've usually already given up and written the for loop.
If you're in JS-and-Go territory and you know someone who's complained about missing filter/map, sharing this is a real favor to them. That's the audience this is built for.
Issues for missing methods or weird edge cases are genuinely valuable. Especially if you can show me the JS behavior you'd expect — that's the spec I'm matching against, and disagreements are usually where the bug is, also PRs are welcome.
Links
- Repo: github.com/bube054/go-js-array-methods
- Docs: pkg.go.dev/github.com/bube054/go-js-array-methods/v2
- The reference I'm matching: MDN Array.prototype If you build something with it, I'd genuinely like to hear about it. Drop a comment or tag me on GitHub.
— @bube054
Top comments (0)