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?
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.
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.
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.
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 _.
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) } }
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...) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With