goappendslice

The most concise way to concatenate 3 or more slices


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.


Solution

  • 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!