>백엔드 개발 >Golang >Go는 클로저에서 캡처된 루프 변수를 어떻게 처리하며, 이것이 왜 중요한가요?

Go는 클로저에서 캡처된 루프 변수를 어떻게 처리하며, 이것이 왜 중요한가요?

Mary-Kate Olsen
Mary-Kate Olsen원래의
2024-12-15 11:56:10809검색

How Does Go Handle Captured Loop Variables in Closures, and Why Does it Matter?

Go에서 캡처된 클로저(루프 변수용)

루프 변수 클로저 이해

Go에서 컴파일러는 내부에서 사용할 루프 변수를 자동으로 캡처할 수 있습니다. 클로저이지만 이 동작은 루프 유형에 따라 다릅니다. for...range 루프에서 루프 변수는 외부 루프의 반복 변수에 대한 참조로 캡처됩니다.

for...range 루프의 참조 폐쇄 이유

Go는 for..를 처리합니다. .range 루프 및 기타 for 루프도 유사합니다. 따라서 for...range 루프의 루프 변수에 대해 캡처된 클로저는 외부 루프의 변수와 동일한 메모리 위치를 참조합니다.

참조 클로저의 결과

이 시나리오에서 수정 사항은 캡처된 클로저의 변수에 적용된 내용은 외부 루프의 변수에도 영향을 미쳐 잠재적으로 예기치 않은 동작이 발생할 수 있습니다. 이 문제를 방지하려면 아래의 "값...범위" 예시와 같이 클로저 내에 루프 변수의 복사본을 생성해야 합니다.

예제 코드

제공된 코드 조각은 루프 변수에 대한 참조 캡처와 해당 참조 캡처 간의 차이점을 보여줍니다. 값:

func main() {
    lab1() // captured closure is not what is expected

    lab2() // captured closure is not what is expected

    lab3() // captured closure behaves ok
}

func lab3() {
    m := make(map[int32]int32)
    for i := 1; i <= 10; i++ {
        m[i] = i
    }

    l := [](func() (int32, int32)){}
    for k, v := range m {
        kLocal, vLocal := k, v // (C) captures just the right values assigned to k and v
        l = append(l, func() (int32, int32) {
            return kLocal, vLocal
        })
    }

    for _, x := range l {
        k, v := x()
        fmt.Println(k, v)
    }
}

func lab2() {
    m := make(map[int32]int32)
    for i := 1; i <= 10; i++ {
        m[i] = i
    }

    l := [](func() (int32, int32)){}
    for k, v := range m {
        l = append(l, func() (int32, int32) {
            kLocal, vLocal := k, v // (B) captures just the last values assigned to k and v from the range
            return kLocal, vLocal
        })
    }

    for _, x := range l {
        k, v := x()
        fmt.Println(k, v)
    }
}

func lab1() {
    m := make(map[int32]int32)
    for i := 1; i <= 10; i++ {
        m[i] = i
    }

    l := [](func() (int32, int32)){}
    for k, v := range m {
        l = append(l, func() (int32, int32) { return k, v }) // (A) captures just the last values assigned to k and v from the range
    }

    for _, x := range l {
        k, v := x()
        fmt.Println(k, v)
    }
}

출력

lab1에서 캡처된 클로저는 예상되는 개별 값 대신 루프의 최종 값을 참조합니다. lab2에서는 생성된 클로저가 외부 범위의 다른 곳에서 참조되는 동일한 루프 변수를 사용하기 때문에 캡처는 여전히 최종 값을 참조합니다. lab3에서는 클로저가 루프 변수의 복사본을 캡처하므로 개별 값을 정확하게 나타냅니다.

위 내용은 Go는 클로저에서 캡처된 루프 변수를 어떻게 처리하며, 이것이 왜 중요한가요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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