Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

116 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-js-array-methods

Go Reference Go Report Card CI License

A comprehensive, high-performance toolkit for slice manipulation in Go, inspired by JavaScript's Array.prototype methods but architected for bare-metal Go performance.

  • Familiar APIFilter, Map, Reduce, Push, Pop, Includes, and 30+ more, named to match their JS counterparts.
  • Zero-Allocation Fast Paths — Core operations on primitives (like Join or ReduceAs) are optimized to bypass interface boxing, running at sub-nanosecond speeds with zero heap allocations.
  • Go 1.23 Iterators — Native support for lazy iteration (iter.Seq, iter.Seq2), allowing massive datasets to be processed with exactly 0 B/op overhead.
  • 100% Test Coverage — Fully verified, edge-case hardened, and production-ready.
  • Two styles — use plain functions (array.Filter(slice, fn)) or the fluent Array[T] type with chainable methods.
  • Immutable by default — every operation returns a new slice; the original is never mutated.
  • Negative indexesAt, Slice, IndexOf, etc. accept negative indexes and return clear errors instead of panicking.
  • Type-safe generics — including a fully generic Map[T, V] that returns []V, not []any.

Install

Requires Go 1.23+ to support native iterators.

go get github.com/bube054/go-js-array-methods/v2@v2.1.0

v2.1.0 update: Added Go 1.23 iter.Seq support (Keys, Values, EntriesIterator) and zero-allocation ReduceAs pipelines. See CHANGELOG.md for details.

Quick start

Functional style

package main

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

func main() {
	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 })

	fmt.Println(doubled) // [4 8]
}

Object-oriented style with Array[T]

package main

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

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

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

	fmt.Println(result) // [6 4 2]
}

Both styles are interchangeable — pick the one that fits your code.

API overview

# Method Status Summary
1 At Index into a slice (supports negative indexes).
2 Concat Join two or more slices into a new slice.
3 CopyWithin Copy a section of a slice to another position within the same slice.
4 Entries Return []Entry{Index, Value}.
5 EntriesIterator Go 1.23 Iterator: Yields (index, value) pairs as iter.Seq2.
6 Every true if every element passes the predicate.
7 Fill Fill a range with a static value.
8 Filter Keep elements that pass the predicate.
9 Find Pointer to the first matching element, or nil.
10 FindIndex Index of the first match, or -1.
11 FindLast Pointer to the last matching element, or nil.
12 FindLastIndex Index of the last match, or -1.
13 Flat Flatten nested []any to a typed []T (configurable depth).
14 FlatMap Not implemented.
15 ForEach Run a callback for each element.
16 Includes true if the slice contains the value.
17 IndexOf First index of a value, or -1.
18 Join Stringify and join elements with a separator (0 allocs for primitives).
19 Keys Go 1.23 Iterator: Yields indexes as iter.Seq[int].
20 LastIndexOf Last index of a value, or -1.
21 Map Transform each element. Returns []V (generic over output type).
22 MapStrict Transform each element to the same type T.
23 Pop Return slice without last element + pointer to popped value.
24 Push Append elements; returns new slice.
25 Reduce Fold to a single value of any type (JS-fidelity dynamic accumulator).
26 ReduceAs 0-Alloc Fast Path: Reduce to a specific type without interface boxing. Empty input with no initial value panics with a TypeError
27 ReduceStrict Fold to a single value of the same type as the elements.
28 ReduceRight Fold from right to left.
29 ReduceRightAs 0-Alloc Fast Path: Right-fold to a specific type without boxing. Empty input with no initial value panics with a TypeError
30 ReduceRightStrict Right-to-left fold with strict typing.
31 Reverse Reverse a slice; returns new slice.
32 Shift Return slice without first element + pointer to shifted value.
33 Slice Sub-slice from start to end (exclusive), supports negative indexes.
34 Some true if any element passes the predicate.
35 Sort Use the standard library's sort / slices packages.
36 Splice Remove and/or insert elements at an index.
37 ToString Comma-separated string representation.
38 UnShift Prepend elements; returns new slice.
39 ValueOf Identity — returns the slice itself.
40 Values Go 1.23 Iterator: Yields values as iter.Seq[T].
41 With Return a copy with the element at index replaced.

For full signatures, runnable examples, and per-method docs, see pkg.go.dev.

Design & Performance Philosophy

  • Zero-Allocation Fast Paths: When type safety is explicitly defined, this library compiles down to bare-metal loops. Operations like ReduceAs and primitive Join bypass Go's escape analysis interface boxing entirely, achieving 0 allocs/op.
  • Dynamic JS-Fidelity vs. Static Speed: Methods like standard Reduce are designed for complete JavaScript parity (allowing an accumulator to dynamically change types), which incurs a runtime boxing tax. For highly optimized, zero-allocation pipelines, use ReduceAs or ReduceStrict.
  • Lazy Iterators (Go 1.23): Using .EntriesIterator(), .Keys(), or .Values() returns native Go iterators. Processing a massive array eagerly allocates memory proportionally, while lazy iterators process the same data with exactly 0 Bytes of heap overhead.
  • Immutability: Every function returns a new slice. The original input is never modified.
  • Negative Indexes: Methods gracefully accept negative indexes (At(-1) gets the last element) and return typed errors instead of panicking on out-of-bounds access.

Examples

A few common patterns. See array/example_test.go for many more (also rendered on pkg.go.dev).

Memory-Free Lazy Iteration (Go 1.23+) Process large datasets without intermediate slice allocations using native iterators:

arr := array.Array[string]{"alice", "bob", "carol"}

for index, value := range arr.EntriesIterator() {
	fmt.Printf("Index: %d, Value: %s\n", index, value)
}

Zero-Allocation Type Reduction (ReduceAs) Safely transform a slice of integers into a completely different type (e.g., a string) without heap allocations:

nums := []int{1, 2, 3}
str, _ := array.ReduceAs(nums, func(acc string, curr, _ int, _ []int) string {
	return acc + strconv.Itoa(curr)
}, "")
// str == "123"

Sum a slice with ReduceStrict:

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)
// flat == []int{1, 2, 3, 4, 5}

Chain transforms with Array[T]:

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

Benchmarks

A representative benchmark suite proving our zero-allocation guarantees lives in array/benchmark_test.go. Run it with:

go test -bench=. -benchmem ./array/

Contributing

Issues and PRs welcome! See CONTRIBUTING.md for the dev loop, coding conventions, and what we look for in a PR.

Changelog

See CHANGELOG.md.

License

MIT

About

This comprehensive module provides an array (no pun intended) of helper functions specifically designed to empower developers in working efficiently with golang slices. It encompasses popular methods like Map, Filter, Reduce, ForEach, Some, and many more, offering streamlined functionalities to enhance your golang coding experience.

Topics

Resources

Contributing

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages