2016-06-17 13 views
10

Ich versuche, mehrere Scheiben zu verschmelzen wie folgt,Concat mehrere Scheiben in 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... 
    ) 
} 

jedoch die eingebaute append() von Anhängen zwei Scheiben der Lage ist, daher wirft es zu viele Argumente anhängen an Kompilierzeit Gibt es eine alternative Funktion, um die Aufgabe zu erfüllen? Oder gibt es eine bessere Möglichkeit, die Slices zusammenzuführen?

Antwort

11

append arbeitet auf einzelne Elemente, nicht auf ganze Scheiben. Fügen Sie jede Scheibe in einer Schleife

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

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

Diese Frage bereits beantwortet wurde, aber ich wollte das hier schreiben, weil die akzeptierte Antwort nicht der effizienteste ist.

Der Grund ist, dass das Erstellen eines leeren Slice und anschließendes Anhängen zu vielen unnötigen Zuordnungen führen kann.

Am effizientesten wäre es, ein Stück vorher zuzuordnen und die Elemente darin zu kopieren. Unten ist ein Paket, das die Verkettung in beide Richtungen implementiert. Wenn Sie einen Benchmark erstellen, können Sie sehen, dass die Vorbelegung ~ 2x schneller ist und viel weniger Speicher belegt.

Benchmark-Ergebnisse:

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 

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