From f63cd2597c83c328a29c2770cb980b733a5f1d74 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 7 Aug 2023 19:00:50 +0200 Subject: [PATCH 1/3] slices: add Concat --- api/next/56353.txt | 1 + src/slices/slices.go | 15 +++++++++++++++ src/slices/slices_test.go | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 api/next/56353.txt diff --git a/api/next/56353.txt b/api/next/56353.txt new file mode 100644 index 00000000000000..fff2600b87e18c --- /dev/null +++ b/api/next/56353.txt @@ -0,0 +1 @@ +pkg slices, func Concat[$0 interface{ ~[]$1 }, $1 interface{}]($0, ...$1) $0 #56353 diff --git a/src/slices/slices.go b/src/slices/slices.go index 725d91d8f5c151..af3f15ffacd560 100644 --- a/src/slices/slices.go +++ b/src/slices/slices.go @@ -493,3 +493,18 @@ func Reverse[S ~[]E, E any](s S) { s[i], s[j] = s[j], s[i] } } + +// Concat return a new slice that combines all values of input slices +func Concat[S ~[]E, E any](dst S, slices ...S) S { + sl := 0 + for i := range slices { + sl += len(slices[i]) + } + dst = Grow(dst, len(dst)+sl) + for _, s := range slices { + if sLen := len(s); sLen != 0 { + dst = append(dst, s...) + } + } + return dst +} diff --git a/src/slices/slices_test.go b/src/slices/slices_test.go index 8ea93c66d76686..835804f126cf10 100644 --- a/src/slices/slices_test.go +++ b/src/slices/slices_test.go @@ -1055,3 +1055,21 @@ func TestInference(t *testing.T) { t.Errorf("Reverse(%v) = %v, want %v", S{4, 5, 6}, s2, want) } } + +func TestConcat(t *testing.T) { + s1 := Concat([]string{}, []string{"a", "b"}, []string{"c"}, nil) + if want := []string{"a", "b", "c"}; !Equal(s1, want) { + t.Errorf("want %v, got %v", want, s1) + } + + s2 := Concat(nil, []int{1, 2}, []int{4}, nil) + if want := []int{1, 2, 4}; !Equal(s2, want) { + t.Errorf("want %v, got %v", want, s2) + } + + s3 := []bool{false, true} + s4 := Concat(s3, nil, []bool{true}) + if want := []bool{false, true, true}; !Equal(s2, want) { + t.Errorf("want %v, got %v", want, s2) + } +} From 8645c5f88c95a028c5cc49dea50c0e8a100811d9 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 7 Aug 2023 19:17:03 +0200 Subject: [PATCH 2/3] fix --- src/slices/slices.go | 4 +--- src/slices/slices_test.go | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/slices/slices.go b/src/slices/slices.go index af3f15ffacd560..4a4859e2410b22 100644 --- a/src/slices/slices.go +++ b/src/slices/slices.go @@ -502,9 +502,7 @@ func Concat[S ~[]E, E any](dst S, slices ...S) S { } dst = Grow(dst, len(dst)+sl) for _, s := range slices { - if sLen := len(s); sLen != 0 { - dst = append(dst, s...) - } + dst = append(dst, s...) } return dst } diff --git a/src/slices/slices_test.go b/src/slices/slices_test.go index 835804f126cf10..2747f1bbdc1fcd 100644 --- a/src/slices/slices_test.go +++ b/src/slices/slices_test.go @@ -1069,7 +1069,7 @@ func TestConcat(t *testing.T) { s3 := []bool{false, true} s4 := Concat(s3, nil, []bool{true}) - if want := []bool{false, true, true}; !Equal(s2, want) { - t.Errorf("want %v, got %v", want, s2) + if want := []bool{false, true, true}; !Equal(s4, want) { + t.Errorf("want %v, got %v", want, s4) } } From 4af94783664a0a1cedd4083cb747539de744b58b Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 7 Aug 2023 20:19:28 +0200 Subject: [PATCH 3/3] as per revew, always allocate --- src/slices/slices.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slices/slices.go b/src/slices/slices.go index 4a4859e2410b22..3a78c7225b44be 100644 --- a/src/slices/slices.go +++ b/src/slices/slices.go @@ -500,9 +500,9 @@ func Concat[S ~[]E, E any](dst S, slices ...S) S { for i := range slices { sl += len(slices[i]) } - dst = Grow(dst, len(dst)+sl) + res := append(make([]E, len(dst)+sl), dst...) for _, s := range slices { - dst = append(dst, s...) + res = append(res, s...) } - return dst + return res }