2016-06-17 7 views
10

मैं इस प्रकार कई स्लाइस मर्ज करने के लिए कोशिश कर रहा हूँ,Concat 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... 
    ) 
} 

हालांकि builtin संलग्न() दो स्लाइस जोड़कर करने में सक्षम है, इसलिए इस पर संलग्न करने के लिए भी कई तर्क फेंकता समय संकलित करें। क्या कार्य प्राप्त करने के लिए कोई वैकल्पिक कार्य है? या स्लाइस मर्ज करने का एक बेहतर तरीका है?

उत्तर

11

append व्यक्तिगत स्लाइसों पर नहीं, व्यक्तिगत तत्वों पर काम करता है। एक पाश

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

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

यह सवाल पहले से ही उत्तर दिया गया है में प्रत्येक टुकड़ा संलग्न है, लेकिन मैं इस यहाँ पोस्ट करने के लिए क्योंकि स्वीकार किए जाते हैं जवाब सबसे कारगर नहीं है चाहता था।

कारण यह है कि एक खाली टुकड़ा बनाना और फिर संलग्न करना कई अनावश्यक आवंटन का कारण बन सकता है।

सबसे प्रभावी तरीका एक टुकड़ा पूर्व आवंटित करना और तत्वों को इसकी प्रतिलिपि बनाना होगा। नीचे एक पैकेज है जो दोनों तरीकों से संगतता लागू करता है। यदि आप बेंचमार्क देखते हैं तो आप देख सकते हैं कि प्री-आवंटन ~ 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) 
    } 
}