Go의 "추가" 기능에서 의도하지 않은 덮어쓰기
Go에서 슬라이스 추가의 미묘한 차이를 탐색하면 때로는 예상치 못한 결과가 발생할 수 있습니다. 이 동작을 보여주는 예를 살펴보겠습니다.
다음 코드를 고려하세요.
import "fmt" type Foo struct { val int } func main() { a := make([]*Foo, 1) a[0] = &Foo{0} b := [3]Foo{Foo{1}, Foo{2}, Foo{3}} for _, e := range b { a = append(a, &e) } for _, e := range a { fmt.Printf("%v ", *e) } }
흥미롭게도 {0} {1} {2} {3}를 인쇄하는 대신 출력은 {0} {3} {3} {3}로 읽습니다. 이 퍼즐을 풀기 위해 "append" 함수를 분석해 보겠습니다.
Go에서 "append"는 요소를 추가하는 슬라이스에 대한 포인터를 기대합니다. 이 예에서는 "a" 슬라이스에 "Foo" 인스턴스에 대한 포인터를 올바르게 저장했습니다.
그러나 배열 "b"의 요소를 반복할 때 미묘한 문제가 발생합니다. "범위" 구문은 실제 요소 자체가 아닌 각 요소의 복사본을 반복합니다. 결과적으로 우리는 최종 반복에서 "Foo{3}"를 가리키는 "Foo" 인스턴스 "e"의 복사본에 포인터를 지속적으로 추가하고 있습니다.
이 동작을 수정하려면 다음을 참조해야 합니다. "추가" 작업에서 "b"의 실제 요소:
for i := range b { a = append(a, &b[i]) }
이 수정을 통해 "b" 내의 요소에 포인터를 직접 추가하여 원하는 결과를 얻을 수 있습니다. {0} {1} {2} {3}.
이러한 동작의 근본적인 이유를 이해하는 것이 중요합니다. Go에서 포인터는 데이터를 조작할 때 메모리 주소로 해석되는 값입니다. 따라서 "범위" 루프는 원래 개체가 아닌 값의 복사본을 반복합니다. 이 지식은 초기 코드에서 세 요소가 동일한 "Foo{3}" 인스턴스를 가리키는 이유를 이해하는 데 도움이 됩니다.
위 내용은 범위 루프에서 포인터를 추가할 때 Go의 'append' 함수가 예상치 못한 결과를 생성하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!