2

I am looking for a way to concisely and efficiently concatenate 3 or more slices in Go.

Let's say I want to concatenate the following slices (all the code can be found here - https://play.golang.org/p/6682YiFF8qG):

a := []int{1, 2, 3}
b := []int{4, 5, 6}
c := []int{7, 8, 9}

My first attempt is by using the append method:

d1 := append(a, b...)
d1 = append(d1, c...) // [1 2 3 4 5 6 7 8 9]

However, this method is verbose and requires 2 append calls for concatenating three slices. So, for n slices, I will need n-1 calls to append, which is not only verbose, but also inefficient as it requires multiple allocations.

My next attempt is to create a variadic function to handle the concatenation with only one new slice allocation:

func concat(slicesOfSlices ...[]int) []int {
    var totalLengthOfSlices int

    for _, slice := range slicesOfSlices {
        totalLengthOfSlices += len(slice)
    }

    arr := make([]int, 0, totalLengthOfSlices)

    for _, slice := range slicesOfSlices {
        arr = append(arr, slice...)
    }

    return arr
}

Then I can use it as follows:

d2 := concat(a, b, c) // [1 2 3 4 5 6 7 8 9]

To illustrate, I want to emulate the following convenient functionality of the spread operator in JavaScript, which I often use in the following way:

const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [7, 8, 9];

const d = [...a, ...b, ...c]; // [1, 2, 3, 4, 5, 6, 7, 8, 9]

In other words, I am looking for a way to do something like d3 := append(a, b, c) or d3 := append(a, b..., c...) but with the standard Go library or using less code than I did.

Note on possible duplicates

I don't think this is a duplicate of the question "How to concatenate two slices" as my question is about concatenating 3 or more slices in the most concise and idiomatic way.

4
  • Please comment why you are voting down this question so my future questions are in line with what is expected on Stack Overflow. Thanks! Commented Nov 24, 2019 at 19:17
  • Of course this is a duplicate of how to append slices. There is no fundamental difference between appending 17 and 18 slices. Commented Nov 24, 2019 at 19:24
  • I agree that there is no fundamental difference, but the question is not about the fundamental difference, it is about the concise syntax.Nick Corin advised me on using a = append(a, append(b, c...)...) to achieve it in one line. Commented Nov 24, 2019 at 19:45
  • There’s no reason to search for “one liners” in go (or most languages for that matter). There’s no global shortage on newline characters, and more readable alternatives still compile to the same instructions. Commented Nov 24, 2019 at 23:57

2 Answers 2

3

You could use your first method of using append like this:

a := []int{1, 2, 3, 4}
b := []int{9, 8, 7, 6}
c := []int{5, 4, 3, 2}

a = append(a, append(b, c...)...)

That being said, I think that your variadic concat function is cleaner and isn't very much code for a utility function.

(Go Playground Link)

Good luck!

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, Nick! a = append(a, append(b, c...)...) is exactly what I was looking for as a one-liner solution
2

For anyone looking for this more recently, go v1.22+ includes a native concat function now:

slices.Concat(a, b, c)

https://pkg.go.dev/slices#Concat

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.