Go에서 컴파일러는 내부에서 사용할 루프 변수를 자동으로 캡처할 수 있습니다. 클로저이지만 이 동작은 루프 유형에 따라 다릅니다. 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!