>백엔드 개발 >Golang >Go에서 슬라이스에 포인터를 추가하면 예기치 않은 덮어쓰기 값이 발생하는 이유는 무엇입니까?

Go에서 슬라이스에 포인터를 추가하면 예기치 않은 덮어쓰기 값이 발생하는 이유는 무엇입니까?

Barbara Streisand
Barbara Streisand원래의
2024-12-15 09:24:10498검색

Why Does Appending Pointers to a Slice in Go Result in Unexpected Overwritten Values?

이상한 Golang "추가" 동작: 슬라이스의 값 덮어쓰기

Golang에서는 슬라이스에 추가할 때 차이점을 이해하는 것이 중요합니다. 포인터 유형과 포인터가 아닌 유형 사이.

예제를 고려해보세요. 코드:

import "fmt"

type Foo struct {
    val int
}

func main() {
    var a = make([]*Foo, 1)
    a[0] = &Foo{0}

    var 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}을 인쇄합니다. 이는 for 루프가 배열 요소의 복사본에서 작동하기 때문입니다.

for ... 범위로 반복할 때 임시 루프 변수가 생성되고 배열 요소의 값이 할당됩니다. 이 경우 임시 변수는 Foo 유형입니다. 그러나 슬라이스에 추가할 때 실제 배열 요소의 주소 대신 임시 변수의 주소가 추가됩니다.

이 임시 변수는 각 루프 반복에서 마지막 요소의 값으로 덮어쓰여집니다. Foo{3}인 배열입니다. 결과적으로 슬라이스에는 배열의 마지막 요소를 가리키는 동일한 포인터에 대한 여러 참조가 포함되어 있습니다.

문제를 해결하려면 루프 변수 대신 배열 요소의 주소를 추가해야 합니다.

for i := range b {
    a = append(a, &b[i])
}

이 수정을 통해 예상한 대로 출력됩니다: {0} {1} {2} {3}.

이 동작은 이해의 중요성을 강조합니다. Go의 유형 시스템과 슬라이스 작업 시 포인터와 비포인터의 구별.

위 내용은 Go에서 슬라이스에 포인터를 추가하면 예기치 않은 덮어쓰기 값이 발생하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.