2016-06-17 8 views
10

Próbuję łączyć kilka plasterków następująco,Concat kilka plasterków w golang

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... 
    ) 
} 

Jednak wbudowane append() jest zdolny do dołączania dwie kromki, dlatego rzuca zbyt wiele argumentów, aby dołączyć w czas kompilacji. Czy istnieje alternatywna funkcja do wykonania tego zadania? czy istnieje lepszy sposób na scalenie plasterków?

Odpowiedz

11

append działa na poszczególnych elementów, a nie na całe plastry. Dołącz każdy plasterek w pętli

routes := []Routes{ 
    WifiUserRoutes, 
    WifiUsageRoutes, 
    WifiLocationRoutes, 
    DashboardUserRoutes, 
    DashoardAppRoutes, 
    RadiusRoutes, 
    AuthenticationRoutes, 
} 

var ApplicationRoutes []Route 
for _, r := range routes { 
    ApplicationRoutes = append(ApplicationRoutes, r...) 
} 
9

Kwestia ta została już odpowiedział, ale chciałem pisać tego tutaj, ponieważ przyjął odpowiedź nie jest najbardziej efektywny.

Powodem jest to, że tworzenie pustego plasterka, a następnie dołączanie może prowadzić do wielu niepotrzebnych przydziałów.

Najbardziej efektywnym sposobem byłoby wstępne przydzielenie plasterka i skopiowanie do niego elementów. Poniżej znajduje się pakiet implementujący konkatenację w obie strony. Jeśli test porównawczy widać, że wstępne przydzielenie jest ~ 2x szybsze i alokuje znacznie mniej pamięci.

Benchmark Wyniki: concat

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 

Opakowanie:

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 
} 

testy Benchmark:

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) 
    } 
}