> 백엔드 개발 > Golang > 범위 루프에서 포인터를 추가할 때 Go의 'append' 함수가 예상치 못한 결과를 생성하는 이유는 무엇입니까?

범위 루프에서 포인터를 추가할 때 Go의 'append' 함수가 예상치 못한 결과를 생성하는 이유는 무엇입니까?

Patricia Arquette
풀어 주다: 2024-12-08 03:08:11
원래의
151명이 탐색했습니다.

Why Does Go's `append` Function Produce Unexpected Results When Appending Pointers from a Range Loop?

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿