Go에서 구조체는 값에 따라 복사되며(1단계의 깊은 복사, 중첩된 구조체도 동일한 규칙에 따라 복사됨), 슬라이스는 값에 따라 복사되지만, 실제 배열은 복사되지 않습니다: 원본과 슬라이스 복사본 모두 동일한 백업 배열을 가리키므로, 한 슬라이스를 통해 변경하면 다른 슬라이스에도 반영됩니다. 배열을 명시적으로 복사하려면 copy()를 사용해야 합니다.
슬라이스 복사 예시:
s1 := []int{1,2,3} s2 := s1 // 동일한 버퍼를 가리킴! s2[0] = 99 fmt.Println(s1) // [99 2 3] // 배열 복사를 위해: s3 := make([]int, len(s1)) copy(s3, s1) s3[0] = 42 fmt.Println(s1) // [99 2 3], s3는 독립적임
구조체를 복사할 때: 구조체가 포인터 필드나 슬라이스 필드를 포함하고 있으면, 값이 아닌 단지 참조만 복사됩니다.
슬라이스를 "복제"하여 그 변경이 원본에 영향을 미치지 않도록 하려면 어떻게 해야 합니까?
잠재적으로 잘못된 답변: 그냥 b := a를 만들면 된다. 맞는 답변:
copy를 사용하여 필요한 길이의 새 슬라이스를 만들고 데이터를 복사해야 합니다:newS := make([]int, len(a)) copy(newS, a)
이야기
설명: DB에 대한 요청을 생성할 때 요청 구조의 슬라이스 필드를 동적으로 변경하였고, 복사 없이 사용하였음. 반복 요청 시 데이터가 섞여 사용자가 잘못된 결과를 받았습니다.
이야기
설명: 데이터 병렬 처리 시 구조체를 단순히 할당으로 복사하고 한 고루틴에서 슬라이스를 확장하는 동안 다른 원본 슬라이스를 병행하여 사용하였습니다. 데이터가 "덮어쓰기" 되어 예측할 수 없는 버그가 발생했습니다.
이야기
설명: 버퍼 구조체를 사용하고, 단순히 할당을 통해 복사하는 것이 중첩된 슬라이스(shallow copy)를 고려하지 않아 한 곳의 변경이 다른 버퍼에 영향을 주었습니다 — 결과적으로 데이터 변경의 출처를 추적하기 어려웠습니다.