結論
b := append(a[:0:0], a...)
解説
a[:0:0]
は a[0:0:0]
の省略で、 Full slice expressions(フルスライス式?)と言います。
-
その構文
a[low : high : max]
最初のインデックス(
low
) が0
の場合、a[: high : max]
に省略することができます。
注意:普通のスライス式 a[0:0]
ですと、 b
が a
と同じメモリを使うことになります。
おまけ
b := make([]T, len(a))
copy(b, a)
OR
b := append([]T(nil), a...)
でも複製できますが、
前者は、nil slice
を non-nil blank slice
に、
後者は、non-nil blank slice
を nil slice
に複製してしまう問題あります。
nil
判定を入れれば問題解消できますが、コードが長くなります。
if a == nil {
b = nil
} else {
b = make([]T, len(a))
copy(b, a)
}
ベンチマーク
テストコード
package main
import (
"testing"
)
const N = 1024 * 1024
type T = int64
var xForMakeCopy = make([]T, N)
var xForAppend = make([]T, N)
var yForMakeCopy []T
var yForAppend []T
func Benchmark_MakeAndCopy(b *testing.B) {
for i := 0; i < b.N; i++ {
yForMakeCopy = make([]T, N)
copy(yForMakeCopy, xForMakeCopy)
}
}
func Benchmark_Append(b *testing.B) {
for i := 0; i < b.N; i++ {
yForAppend = append(xForAppend[:0:0], xForAppend...)
}
}
テスト結果
❯ go version
go version go1.14.2 darwin/amd64
❯ go test -bench=.
goos: darwin
goarch: amd64
Benchmark_MakeAndCopy-8 1142 990016 ns/op
Benchmark_Append-8 2289 526206 ns/op
append
が copy
より2倍ぐらい早いようでした。
参考
How to efficiently clone a slice?
元記事