From 0248ce75f5f4cdf2076dfbc82ee6d06e0cfa6506 Mon Sep 17 00:00:00 2001 From: Hiroyuki Toda Date: Sat, 22 Aug 2026 13:37:37 +0900 Subject: [PATCH] Add ForEachErr() func --- slice.go | 11 +++++++++++ slice_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/slice.go b/slice.go index dd556750..7a5b88a1 100644 --- a/slice.go +++ b/slice.go @@ -195,6 +195,17 @@ func ForEach[T any](collection []T, callback func(item T, index int)) { } } +// ForEachErr iterates over elements of collection and invokes callback for each element. +// It returns the first error returned by the iteratee function. +func ForEachErr[T any](collection []T, callback func(item T, index int) error) error { + for i := range collection { + if err := callback(collection[i], i); err != nil { + return err + } + } + return nil +} + // ForEachWhile iterates over elements of collection and invokes predicate for each element // collection return value decide to continue or break, like do while(). // Play: https://go.dev/play/p/QnLGt35tnow diff --git a/slice_test.go b/slice_test.go index 88143c8f..c3b4b870 100644 --- a/slice_test.go +++ b/slice_test.go @@ -789,6 +789,31 @@ func TestForEach(t *testing.T) { is.IsIncreasing(callParams2) } +func TestForEachErr(t *testing.T) { + t.Parallel() + is := assert.New(t) + + // check of callback is called for every element and in proper order + + var callParams1 []string + var callParams2 []int + + err := ForEachErr([]string{"a", "b", "c"}, func(item string, i int) error { + if item == "c" { + return errors.New("'c' is not allowed") + } + callParams1 = append(callParams1, item) + callParams2 = append(callParams2, i) + return nil + }) + + is.Equal([]string{"a", "b"}, callParams1) + is.Equal([]int{0, 1}, callParams2) + is.IsIncreasing(callParams2) + is.Error(err) + is.Equal("'c' is not allowed", err.Error()) +} + func TestForEachWhile(t *testing.T) { t.Parallel() is := assert.New(t)