Конкатентные фрагменты в голанге
Я пытаюсь объединить несколько фрагментов следующим образом,
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...
)
}
Однако встроенный append() способен добавлять два среза, поэтому он выдает слишком много аргументов для добавления во время компиляции. Есть ли альтернативная функция для достижения этой задачи? или есть лучший способ объединить срезы?
Ответы
Ответ 1
append
работает с отдельными элементами, а не с целыми фрагментами. Добавить каждый срез в цикле
routes := []Routes{
WifiUserRoutes,
WifiUsageRoutes,
WifiLocationRoutes,
DashboardUserRoutes,
DashoardAppRoutes,
RadiusRoutes,
AuthenticationRoutes,
}
var ApplicationRoutes []Route
for _, r := range routes {
ApplicationRoutes = append(ApplicationRoutes, r...)
}
Ответ 2
Этот вопрос уже был дан, но я хотел опубликовать его здесь, потому что принятый ответ не самый эффективный.
Причина в том, что создание пустого фрагмента, а затем добавление может привести к множеству ненужных распределений.
Наиболее эффективным способом было бы предварительно выделить срез и скопировать в него элементы. Ниже представлен пакет, который реализует конкатенацию в обоих направлениях. Если вы проводите тестирование, вы увидите, что предварительное выделение ~ 2x быстрее и выделяет гораздо меньше памяти.
Результаты тестов:
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
Пакет 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
}
Тесты тестов:
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)
}
}