it-swarm.com.de

Warum kann ich ein Slice nicht mit copy () duplizieren?

Ich muss eine Kopie eines Slice in Go erstellen und beim Lesen der Dokumente steht mir eine copy -Funktion zur Verfügung.

Die eingebaute Kopierfunktion kopiert Elemente von einem Quell-Slice in ein Ziel-Slice. (Als Sonderfall werden auch Bytes aus einer Zeichenfolge in ein Byte-Segment kopiert.) Quelle und Ziel überschneiden sich möglicherweise. Copy gibt die Anzahl der kopierten Elemente zurück, dh das Minimum von len (src) und len (dst).

Aber wenn ich es mache:

arr := []int{1, 2, 3}
tmp := []int{}
copy(tmp, arr)
fmt.Println(tmp)
fmt.Println(arr)

Mein tmp ist leer wie vorher (ich habe sogar versucht arr, tmp):

[]
[1 2 3]

Sie können es auf go Spielplatz überprüfen. Warum kann ich ein Slice nicht kopieren?

92
Salvador Dali

Das eingebaute copy(dst, src) kopiert min(len(dst), len(src)) -Elemente.

Wenn also Ihr dst leer ist (len(dst) == 0), wird nichts kopiert.

Versuchen Sie 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)

Ausgabe (wie erwartet):

[1 2 3]
[1 2 3]

Leider ist dies nicht im builtin -Paket dokumentiert, sondern in der Go-Sprachspezifikation: Anhängen und Kopieren von Slices :

Die Anzahl der kopierten Elemente ist das Minimum von len(src) und len(dst).

Bearbeiten:

Schließlich wurde die Dokumentation von copy() aktualisiert und enthält nun die Tatsache, dass die minimale Länge von Quelle und Ziel kopiert wird:

Copy gibt die Anzahl der kopierten Elemente zurück, wobei es sich um das Minimum von len (src) und len (dst) handelt.

160
icza

Eine andere einfache Möglichkeit, dies zu tun, ist die Verwendung von append, wodurch das Slice im Prozess zugewiesen wird.

arr := []int{1, 2, 3}
tmp := append([]int(nil), arr...)  // Notice the ... splat
fmt.Println(tmp)
fmt.Println(arr)

Ausgabe (wie erwartet):

[1 2 3]
[1 2 3]

Eine Abkürzung zum Kopieren von Array arr wäre append([]int(nil), arr...)

https://play.golang.org/p/sr_4ofs5GW

17
Dave

Wenn Ihre Scheiben die gleiche Größe hätten, es würde funktionieren :

arr := []int{1, 2, 3}
tmp := []int{0, 0, 0}
i := copy(tmp, arr)
fmt.Println(i)
fmt.Println(tmp)
fmt.Println(arr)

Würde geben:

3
[1 2 3]
[1 2 3]

Von " Go Slices: Verwendung und Interna ":

Die Kopierfunktion unterstützt das Kopieren zwischen Slices unterschiedlicher Länge (, sie kopiert nur bis zur kleineren Anzahl von Elementen )

Das übliche Beispiel ist:

t := make([]byte, len(s), (cap(s)+1)*2)
copy(t, s)
s = t
12
VonC

Die copy () wird für die kürzeste Länge von dst und src ausgeführt, daher müssen Sie die dst auf die gewünschte Länge initialisieren.

A := []int{1, 2, 3}
B := make([]int, 3)
copy(B, A)
C := make([]int, 2)
copy(C, A)
fmt.Println(A, B, C)

Ausgabe:

[1 2 3] [1 2 3] [1 2]

Sie können alle Elemente in einer Zeile mit append () initialisieren und in ein Null-Slice kopieren.

x := append([]T{}, []...)

Beispiel:

A := []int{1, 2, 3}
B := append([]int{}, A...)
C := append([]int{}, A[:2]...)
fmt.Println(A, B, C)    

Ausgabe:

[1 2 3] [1 2 3] [1 2]

Verwenden Sie für mehr als 1.000 Elemente im Vergleich zur Zuweisung + copy () den Befehl append. Tatsächlich kann der Unterschied unter 1.000 vernachlässigt werden. Machen Sie es zu einer Faustregel, es sei denn, Sie haben viele Schnitte.

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
10
Esze

Die Go-Programmiersprachenspezifikation

Slices anhängen und kopieren

Die Funktion copy kopiert Slice-Elemente von einer Quell-Quelle in eine Ziel-Quelle und gibt die Anzahl der kopierten Elemente zurück. Beide Argumente müssen den gleichen Elementtyp T haben und einem Slice vom Typ [] T zuweisbar sein. Die Anzahl der kopierten Elemente ist das Minimum von len (src) und len (dst). Als Sonderfall akzeptiert copy auch ein Zielargument, das dem Typ [] Byte mit einem Quellargument eines Zeichenfolgentyps zugewiesen werden kann. Dieses Formular kopiert die Bytes aus der Zeichenfolge in den Byte-Slice.

copy(dst, src []T) int
copy(dst []byte, src string) int

tmp benötigt genügend Platz für arr. Zum Beispiel,

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)
}

Ausgabe:

[1 2 3]
[1 2 3]
2
peterSO