¿Por qué no puedo duplicar un slice con `copy()` en golang?
Necesito hacer una copia de un slice en go y leyendo los documentos hay una función copy a mi disposición.
La función copy integrada copia elementos de un segmento de origen en un rebanada de destino. (Como caso especial, también copiará bytes de un cadena a una porción de bytes.) La fuente y el destino pueden superponerse. Copiar devuelve el número de elementos copiados, que será el mínimo de len (src) y len(dst).
Pero cuando do
arr := []int{1, 2, 3}
tmp := []int{}
copy(tmp, arr)
fmt.Println(tmp)
fmt.Println(arr)
Mi tmp
está vacío como estaba antes (incluso traté de usar arr, tmp):
[]
[1 2 3]
Puedes comprobarlo en go playground. Entonces, ¿por qué no puedo copiar una rebanada?
5 answers
El builtin copy(dst, src)
copia elementos min(len(dst), len(src))
.
Así que si su dst
está vacío (len(dst) == 0
), nada será copiado.
Intente tmp := make([]int, len(arr))
(Ir al Parque Infantil):
arr := []int{1, 2, 3}
tmp := make([]int, len(arr))
copy(tmp, arr)
fmt.Println(tmp)
fmt.Println(arr)
Salida (como se esperaba):
[1 2 3]
[1 2 3]
Desafortunadamente esto no está documentado en el builtin
paquete, pero está documentado en el Ir Especificación de idioma: Anexar y copiar sectores:
El número de elementos copiados es el mínimo de
len(src)
ylen(dst)
.
Editar:
Finalmente se ha actualizado la documentación de copy()
y ahora contiene el hecho de que se copiará la longitud mínima de origen y destino:
Copy devuelve el número de elementos copiados, que será el mínimo de len(src) y len(dst).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-22 06:28:24
Si sus rebanadas fueran del mismo tamaño, funcionaría :
arr := []int{1, 2, 3}
tmp := []int{0, 0, 0}
i := copy(tmp, arr)
fmt.Println(i)
fmt.Println(tmp)
fmt.Println(arr)
Daría:
3
[1 2 3]
[1 2 3]
Desde " Go Slices: uso e internos":
La función copy admite la copia entre segmentos de diferentes longitudes (se copiará solo hasta el menor número de elementos)
El ejemplo habitual es:
t := make([]byte, len(s), (cap(s)+1)*2)
copy(t, s)
s = t
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-12 07:47:18
Otra forma sencilla de hacer esto es usando append
que asignará el segmento en el proceso.
arr := []int{1, 2, 3}
tmp := append([]int(nil), arr...) // Notice the ... splat
fmt.Println(tmp)
fmt.Println(arr)
Salida (como se esperaba):
[1 2 3]
[1 2 3]
Así que una abreviatura para copiar matriz arr
sería append([]int(nil), arr...)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-26 22:21:06
Copy() se ejecuta durante la menor longitud de dst y src, por lo que debe inicializar el dst a la longitud deseada.
A := []int{1, 2, 3}
B := make([]int, 3)
copy(B, A)
C := make([]int, 2)
copy(C, A)
fmt.Println(A, B, C)
Salida:
[1 2 3] [1 2 3] [1 2]
Puede inicializar y copiar todos los elementos en una línea usando append() a un segmento nil.
x := append([]T{}, []...)
Ejemplo:
A := []int{1, 2, 3}
B := append([]int{}, A...)
C := append([]int{}, A[:2]...)
fmt.Println(A, B, C)
Salida:
[1 2 3] [1 2 3] [1 2]
Comparando con allocation+copy(), para más de 1.000 elementos, use append. En realidad debajo de 1,000 la diferencia puede ser descuidada, que sea una regla de oro a menos que tenga muchos rebanada.
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-02 22:29:32
La Especificación del Lenguaje de Programación Go
La función copy copia los elementos slice de un src de origen a un destino dst y devuelve el número de elementos copiados. Ambos los argumentos deben tener el mismo tipo de elemento T y deben ser asignables a una rebanada de tipo []T. El número de elementos copiados es el mínimo de len (src) y len (dst). Como un caso especial, copia también acepta un destino argumento asignable al tipo [] byte con un argumento de origen de un tipo de cadena. Este formulario copia los bytes de la cadena en el byte slice.
copy(dst, src []T) int copy(dst []byte, src string) int
tmp
necesita espacio suficiente para arr
. Por ejemplo,
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)
}
Salida:
[1 2 3]
[1 2 3]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-12 05:37:53