3
1

More than 3 years have passed since last update.

[Go言語] Sliceを完璧に複製するには? (How to perfectly clone a slice?)

Posted at

結論

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] ですと、 ba と同じメモリを使うことになります。

おまけ

b := make([]T, len(a))
copy(b, a)

OR

b := append([]T(nil), a...)

でも複製できますが、

前者は、nil slicenon-nil blank slice に、

後者は、non-nil blank slicenil 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

appendcopy より2倍ぐらい早いようでした。

参考

How to efficiently clone a slice?

元記事

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1