[go] `copy ()`로 슬라이스를 복제 할 수없는 이유는 무엇입니까?

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]

이동 놀이터 에서 확인할 수 있습니다 . 그렇다면 슬라이스를 복사 할 수없는 이유는 무엇입니까?



답변

내장 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 Language Specification : Appending to and copying slices에 문서화되어 있습니다 .

복사 된 요소의 수는 len(src)및 의 최소값입니다 len(dst).

편집하다:

마지막으로의 문서 copy()가 업데이트되었으며 이제 소스 및 대상의 최소 길이가 복사된다는 사실이 포함됩니다.

Copy는 복사 된 요소의 수를 반환하며, 이는 len (src) 및 len (dst) 의 최소값 입니다.


답변

이를 수행하는 또 다른 간단한 방법 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...)

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


답변

슬라이스 크기 가 같으면 작동합니다 .

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 : 사용법 및 내부 “에서 :

복사 기능은 길이가 다른 슬라이스 사이의 복사를 지원합니다 ( 소수의 요소까지만 복사합니다 ).

일반적인 예는 다음과 같습니다.

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 슬라이스에 모든 요소를 ​​한 줄에 초기화하고 복사 할 수 있습니다.

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 개 이상의 요소에 대해서는 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


답변

Go 프로그래밍 언어 사양

슬라이스에 추가 및 복사

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]


답변

다음은 슬라이스를 복사하는 방법입니다. 나는 조금 늦었지만 @Dave보다 더 간단하고 빠른 대답이 있습니다. 이것은 @ Dave ‘s와 같은 코드에서 생성 된 명령어입니다. 이것들 은 내 것이 생성 한 지시입니다. 보시다시피 지침이 훨씬 적습니다. 하는 것은 append(slice)슬라이스를 복사하는 것입니다. 이 코드 :

package main

import "fmt"

func main() {
    var foo = []int{1, 2, 3, 4, 5}
    fmt.Println("foo:", foo)
    var bar = append(foo)
    fmt.Println("bar:", bar)
    bar = append(bar, 6)
    fmt.Println("foo after:", foo)
    fmt.Println("bar after:", bar)
}

다음을 출력합니다.

foo: [1 2 3 4 5]
bar: [1 2 3 4 5]
foo after: [1 2 3 4 5]
bar after: [1 2 3 4 5 6]


답변