슬라이스 추가 및 원본 슬라이스에 미치는 영향 이해
Go에서 슬라이스 작업을 할 때 추가 기능은 새 요소를 추가하는 데 자주 사용됩니다. 기존 슬라이스에. 그러나 많은 개발자는 이 추가 작업이 원본 슬라이스도 수정할 수 있다는 사실에 놀랄 수 있습니다.
검토 중인 코드
다음 코드 조각을 고려하세요.
func someFunc(A []int) int { for i := 0; i < len(A); i++ { tempA := A // copy the slice by value fmt.Println("A: ", A) fmt.Println("tempA: ", A) fmt.Println() newArr = remove(tempA, i) if isAesthetic(newArr) { ways++ } } } func remove(slice []int, s int) []int { return append(slice[:s], slice[s+1:]...) }
여기서 someFunc 함수는 슬라이스 A를 입력으로 사용하고 tempA라는 A의 복사본을 만든 다음 제거 함수를 호출하여 tempA에서 요소를 제거합니다. 작동 중인 함수를 검사하면 다음 콘솔 출력을 확인할 수 있습니다.
A: [3 4 5 3 7] tempA: [3 4 5 3 7] A: [4 5 3 7 7] tempA: [4 5 3 7 7] A: [4 3 7 7 7] tempA: [4 3 7 7 7] A: [4 3 7 7 7] tempA: [4 3 7 7 7]
놀라운 부작용
코드가 실행되면 다음의 내용이 인쇄됩니다. A와 tempA 둘 다, tempA에서 추가가 호출된 후에 원래 슬라이스 A도 수정되었음을 나타냅니다. A의 값별 복사본이 tempA에 대한 변경 사항과 독립적일 것으로 예상하기 때문에 이 동작은 언뜻 보기에는 직관에 어긋나는 것처럼 보일 수 있습니다.
그러나 이 현상은 슬라이스가 구현되는 방식의 직접적인 결과입니다. 이동 중. 슬라이스는 기본적으로 헤더와 기본 배열에 대한 포인터로 구성된 경량 데이터 구조입니다. 헤더에는 슬라이스의 길이와 용량에 대한 정보가 포함되고 포인터는 슬라이스의 첫 번째 요소를 가리킵니다.
tempA에 A 값을 할당하면 기본적으로 다음을 가리키는 새 슬라이스 헤더가 생성됩니다. A와 동일한 기본 배열입니다. 따라서 두 슬라이스가 모두 동일한 데이터를 참조하므로 tempA에 대한 모든 변경 사항은 A에도 반영됩니다.
슬라이스 헤더 및 배열 이해
이 동작을 더 자세히 이해하려면 Go에서 슬라이스 헤더와 배열이 상호 작용하는 방식을 이해하는 것이 도움이 됩니다. 배열에는 동일한 유형의 연속된 요소 블록이 포함되어 있습니다. 반면에 슬라이스는 배열 섹션의 동적 보기를 제공합니다. 이는 배열 내의 연속적인 요소 집합을 설명하지만 기본 배열 데이터를 소유하지는 않습니다.
[]T{e1, e2, ..., 구문을 사용하여 배열에서 슬라이스를 생성하는 경우 en}, 기본적으로 배열의 첫 번째 요소를 가리키는 새 슬라이스 헤더를 생성합니다. 슬라이스의 길이는 n으로 설정하고, 용량은 슬라이스 뒤 배열의 남은 길이로 설정합니다.
마찬가지로 []T(arr) 구문을 사용하여 슬라이스 헤더를 생성하면, arr과 동일한 기본 배열을 가리키는 슬라이스를 생성하고 있습니다. 슬라이스의 길이는 arr의 길이로 설정되고, 용량은 arr의 용량으로 설정됩니다.
의미 및 모범 사례
슬라이스와 배열의 관계를 이해하면 잠재적인 함정을 피하고 보다 효율적인 Go 코드를 작성하는 데 도움이 될 수 있습니다. 슬라이스 작업 시 다음 사항에 유의하세요.
Go 슬라이스의 내부를 이해하면 유연성과 효율성을 활용하는 동시에 코드가 의도한 대로 작동하도록 할 수 있습니다. 슬라이스 헤더와 배열의 미묘한 차이를 수용함으로써 Go에서 슬라이싱 기술을 익히고 이 다용도 데이터 구조의 잠재력을 최대한 활용할 수 있습니다.
위 내용은 Go 슬라이스 복사본에 추가하면 원본 슬라이스도 수정되는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!