2014-10-17 2 views
6

초보자 프로그래머로 이동하십시오. 호출자가 배열의 원래 요소를 변경하지 않도록 슬라이스 (및 기본 배열의 일부)를 복제해야합니다.Go 조각을 복제하는 일반적인 방법은 무엇입니까?

func duplicateSliceOfSomeType(sliceOfSomeType []SomeType) []SomeType { 
    dulicate := make([]SomeType, len(sliceOfSomeType)) 
    copy(duplicate, sliceOfSomeType) 
    return duplicate 
} 

그러나 일반적으로 같은 방법으로 만들 수있는 방법은 아마도 제네릭하지 않고있다 : 나는 특정 유형의 배열이 작업을 수행하는 함수를 작성할 수있을 것 같아요? 당신은 조각의 단순 복사본을 만들 간단한 문장을 쓸 수

func duplicateSlice(slice []?) []?{ 
    duplicate := make([]?, len(slice)) 
    copy(duplicate, slice) 
    return duplicate 
} 

답변

20

,

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

, 예를 들어

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

,

package main 

import "fmt" 

type T int 

func main() { 
    a := []T{4, 2} 

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

    fmt.Println(&a[0], a, &b[0], b) 
    b[0] = 9 
    fmt.Println(&a[0], a, &b[0], b) 
} 

출력 :

0x10328000 [4 2] 0x10328020 [4 2] 
0x10328000 [4 2] 0x10328020 [9 2] 

칙 :

Common difficulties with reflection

명 가고 처음 사용하는 경우, 그들은 전혀 반사를 사용해서는 안됩니다.

-rob

전문가의 경우에도 반사가 미묘합니다. 그것은 언어가 얼마나 작동하는지에 대한 아주 기본적인 것들을 알게되는 것에 따라 이해되고, 어느 정도 구현 되는가에 대한 세부 사항을 보여줍니다. 그것도 경험이 풍부한 프로그래머들에게 어리둥절해질 수 있습니다; 새롭게 에 대해 Gophers 발행일은 을 먼저 배우는 것이 훨씬 더 중요하고 간단합니다. 너무 일찍 반사를 배우는 사람들은 스스로 구름을 혼동합니다. 그 기본에 대한 이해. 사진의 나머지 부분이 분명해질 때까지 팔의 길이로 유지하는 것이 가장 좋습니다.

-rob 말했다

,

package main 

import (
    "fmt" 
    "reflect" 
) 

func CopySlice(s interface{}) interface{} { 
    t, v := reflect.TypeOf(s), reflect.ValueOf(s) 
    c := reflect.MakeSlice(t, v.Len(), v.Len()) 
    reflect.Copy(c, v) 
    return c.Interface() 
} 

type T int 

func main() { 

    { 
     // append 
     a := []T{4, 2} 
     b := append([]T(nil), a...) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

    { 
     // make and copy 
     a := []T{4, 2} 
     b := make([]T, len(a)) 
     copy(b, a) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

    { 
     // reflection 
     a := []T{4, 2} 
     b := CopySlice(a).([]T) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

} 

출력 : 당신은 특별히 reflect.Copyreflect 패키지를 사용하여 모든 유형의 사본을 할 수

0xc20800a200 [4 2] 0xc20800a210 [4 2] 
0xc20800a200 [4 2] 0xc20800a210 [9 2] 
0xc20800a290 [4 2] 0xc20800a2a0 [4 2] 
0xc20800a290 [4 2] 0xc20800a2a0 [9 2] 
0xc20800a310 [4 2] 0xc20800a320 [4 2] 
0xc20800a310 [4 2] 0xc20800a320 [9 2] 
+0

그래서 본질적으로'a' 원소를'b' 원소에 할당 된 새로운 배열을위한 새로운 빈 조각에 추가합니다, 맞습니까? – Kaiged

+0

'append' 메쏘드는'make' /'copy' 메쏘드만큼 성능이 좋습니까? – Kaiged

+0

@Kaiged :'nil' 슬라이스에 추가하면'make'와'copy'로 변환됩니다. 내 수정 된 답변을 참조하십시오. – peterSO

관련 문제