douyo770657
douyo770657
2016-06-17 14:39

在golang中连接多个切片

已采纳

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?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dongyuan9292 dongyuan9292 5年前

    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...)
    }
    
    点赞 评论 复制链接分享
  • dtxq82489 dtxq82489 5年前

    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)
        }
    }
    
    点赞 评论 复制链接分享

相关推荐