Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concat multiple slices in golang

Tags:

go

I'm trying to merge multiple slices as follows,

package routes  import (     "net/http" )  type Route struct {     Name        string     Method      string     Pattern     string     Secured     bool     HandlerFunc http.HandlerFunc }  type Routes []Route  var ApplicationRoutes Routes  func init() {     ApplicationRoutes = append(         WifiUserRoutes,         WifiUsageRoutes,         WifiLocationRoutes,         DashboardUserRoutes,         DashoardAppRoutes,         RadiusRoutes,         AuthenticationRoutes...     ) } 

However the builtin append() is capable of appending two slices, hence it throws too many arguments to append at compile time. Is there an alternative function to achieve the task? or is there a better way to merge the slices?

like image 579
Anuruddha Avatar asked Jun 17 '16 14:06

Anuruddha


People also ask

How do you concatenate slices in Golang?

When it comes to appending a slice to another slice, we need to use the variadic function signature dots. In variadic functions in Golang, we can pass a variable number of arguments to the function and all the numbers can be accessed with the help of the argument name.

How do you concatenate slices?

Type) []Type The append built-in function appends elements to the end of a slice. If it has sufficient capacity, the destination is resliced to accommodate the new elements. If it does not, a new underlying array will be allocated. Append returns the updated slice.

How do you add three slices in Golang?

Slice concatenation in Go is easily achieved by leveraging the built-in append() function. It takes a slice ( s1 ) as its first argument, and all the elements from a second slice ( s2 ) as its second.

How do you add two arrays in Golang?

Go Program to Add Two Arrays Example 2 In this Golang example, we used the for loop range (for x, _ := range addArr1) and performed the addition. You can also rewrite the for loop as (for x := range addArr1). To show you the syntax, we left that _.


Video Answer


2 Answers

This question has been answered already, but I wanted to post this here because the accepted answer is not the most efficient.

The reason is that creating an empty slice and then appending can lead to many unnecessary allocations.

The most efficient way would be to pre-allocate a slice and copy the elements into it. Below is a package which implements the concatenation both ways. If you benchmark you can see that pre-allocating is ~2x faster and allocates much less memory.

Benchmark Results:

go test . -bench=. -benchmem testing: warning: no tests to run BenchmarkConcatCopyPreAllocate-8    30000000            47.9 ns/op        64 B/op          1 allocs/op BenchmarkConcatAppend-8             20000000           107 ns/op         112 B/op          3 allocs/op 

Package concat:

package concat  func concatCopyPreAllocate(slices [][]byte) []byte {     var totalLen int     for _, s := range slices {         totalLen += len(s)     }     tmp := make([]byte, totalLen)     var i int     for _, s := range slices {         i += copy(tmp[i:], s)     }     return tmp }  func concatAppend(slices [][]byte) []byte {     var tmp []byte     for _, s := range slices {         tmp = append(tmp, s...)     }     return tmp } 

Benchmark tests:

package concat  import "testing"  var slices = [][]byte{     []byte("my first slice"),     []byte("second slice"),     []byte("third slice"),     []byte("fourth slice"),     []byte("fifth slice"), }  var B []byte  func BenchmarkConcatCopyPreAllocate(b *testing.B) {     for n := 0; n < b.N; n++ {         B = concatCopyPreAllocate(slices)     } }  func BenchmarkConcatAppend(b *testing.B) {     for n := 0; n < b.N; n++ {         B = concatAppend(slices)     } } 
like image 148
Cameron Sparr Avatar answered Sep 20 '22 13:09

Cameron Sparr


append operates on individual elements, not on entire slices. Append each slice in a loop

routes := []Routes{     WifiUserRoutes,     WifiUsageRoutes,     WifiLocationRoutes,     DashboardUserRoutes,     DashoardAppRoutes,     RadiusRoutes,     AuthenticationRoutes, }  var ApplicationRoutes []Route for _, r := range routes {     ApplicationRoutes = append(ApplicationRoutes, r...) } 
like image 44
JimB Avatar answered Sep 19 '22 13:09

JimB