Goでスライスのコピーを作成する必要があり、ドキュメントを読むと、自由に copy 関数があります。
Copy組み込み関数は、ソーススライスからターゲットスライスに要素をコピーします。 (特殊なケースとして、文字列からバイトをスライスにコピーします。)ソースと宛先が重複する場合があります。コピーは、コピーされた要素の数を返します。これは、len(src)とlen(dst)の最小値になります。
しかし、私がするとき:
arr := []int{1, 2, 3}
tmp := []int{}
copy(tmp, arr)
fmt.Println(tmp)
fmt.Println(arr)
私のtmp
は以前のように空です(arr, tmp
を使用しようとしました):
[]
[1 2 3]
外出先で確認できます playground 。では、なぜスライスをコピーできないのですか?
組み込みの copy(dst, src)
は、min(len(dst), len(src))
要素をコピーします。
したがって、dst
が空(len(dst) == 0
)の場合、何もコピーされません。
tmp := make([]int, len(arr))
を試してください( Go Playground ):
arr := []int{1, 2, 3}
tmp := make([]int, len(arr))
copy(tmp, arr)
fmt.Println(tmp)
fmt.Println(arr)
出力(予想どおり):
[1 2 3]
[1 2 3]
残念ながら、これは builtin
パッケージには文書化されていませんが、 Go言語仕様:スライスへの追加とコピー :
コピーされる要素の数は、
len(src)
とlen(dst)
の最小値です。
編集:
最後に、copy()
のドキュメントが更新され、ソースと宛先の最小長がコピーされるという事実が含まれるようになりました。
コピーは、コピーされた要素の数を返します。これは、len(src)とlen(dst)のminimumになります。
別の簡単な方法は、プロセスでスライスを割り当てるappend
を使用することです。
arr := []int{1, 2, 3}
tmp := append([]int(nil), arr...) // Notice the ... splat
fmt.Println(tmp)
fmt.Println(arr)
出力(予想どおり):
[1 2 3]
[1 2 3]
したがって、配列arr
をコピーするための省略形はappend([]int(nil), arr...)
になります。
スライスが同じサイズの場合、- それは動作します :
arr := []int{1, 2, 3}
tmp := []int{0, 0, 0}
i := copy(tmp, arr)
fmt.Println(i)
fmt.Println(tmp)
fmt.Println(arr)
与えるだろう:
3
[1 2 3]
[1 2 3]
「 Go Slices:usage and internals 」から:
コピー機能は、異なる長さのスライス間でのコピーをサポートします(少数の要素までしかコピーしません)
通常の例は次のとおりです。
t := make([]byte, len(s), (cap(s)+1)*2)
copy(t, s)
s = t
Copy()はdstとsrcの最小の長さで実行されるため、dstを目的の長さに初期化する必要があります。
A := []int{1, 2, 3}
B := make([]int, 3)
copy(B, A)
C := make([]int, 2)
copy(C, A)
fmt.Println(A, B, C)
出力:
[1 2 3] [1 2 3] [1 2]
Append()を使用してnilスライスにすべての要素を初期化し、1行でコピーできます。
x := append([]T{}, []...)
例:
A := []int{1, 2, 3}
B := append([]int{}, A...)
C := append([]int{}, A[:2]...)
fmt.Println(A, B, C)
出力:
[1 2 3] [1 2 3] [1 2]
1,000個を超える要素について、allocation + copy()と比較するには、appendを使用します。実際に1,000を下回ると、その差は無視される可能性があります。スライスが多くない場合は、経験則としてお試しください。
BenchmarkCopy1-4 50000000 27.0 ns/op
BenchmarkCopy10-4 30000000 53.3 ns/op
BenchmarkCopy100-4 10000000 229 ns/op
BenchmarkCopy1000-4 1000000 1942 ns/op
BenchmarkCopy10000-4 100000 18009 ns/op
BenchmarkCopy100000-4 10000 220113 ns/op
BenchmarkCopy1000000-4 1000 2028157 ns/op
BenchmarkCopy10000000-4 100 15323924 ns/op
BenchmarkCopy100000000-4 1 1200488116 ns/op
BenchmarkAppend1-4 50000000 34.2 ns/op
BenchmarkAppend10-4 20000000 60.0 ns/op
BenchmarkAppend100-4 5000000 240 ns/op
BenchmarkAppend1000-4 1000000 1832 ns/op
BenchmarkAppend10000-4 100000 13378 ns/op
BenchmarkAppend100000-4 10000 142397 ns/op
BenchmarkAppend1000000-4 2000 1053891 ns/op
BenchmarkAppend10000000-4 200 9500541 ns/op
BenchmarkAppend100000000-4 20 176361861 ns/op
関数copyは、ソースsrcから宛先dstにスライス要素をコピーし、コピーされた要素の数を返します。両方の引数は同一の要素タイプTを持ち、タイプ[] Tのスライスに割り当て可能でなければなりません。コピーされる要素の数は、len(src)とlen(dst)の最小値です。特殊なケースとして、copyは、文字列型のソース引数とともに[] byte型に割り当て可能な宛先引数も受け入れます。この形式は、文字列からバイトスライスにバイトをコピーします。
copy(dst, src []T) int copy(dst []byte, src string) int
tmp
には、arr
に十分なスペースが必要です。例えば、
package main
import "fmt"
func main() {
arr := []int{1, 2, 3}
tmp := make([]int, len(arr))
copy(tmp, arr)
fmt.Println(tmp)
fmt.Println(arr)
}
出力:
[1 2 3]
[1 2 3]