Go에서 캡처된 클로저(루프 변수용)
Go 컴파일러는 for...range 루프 변수를 로컬에서 할당된 대로 자동으로 캡처하지 않습니다. 클로저 변수. 대신 Go는 모든 for 루프(for...range 루프 포함)를 유사하게 처리하므로 예상되는 동작을 보장하기 위해 루프 변수를 로컬 클로저에 명시적으로 복사해야 합니다.
루프 변수 복사 이유
이러한 동작은 Go의 일관된 for 루프 처리에서 비롯됩니다. for...range 루프를 포함한 모든 유형의 for 루프에서 루프 변수의 범위는 루프 블록으로 지정됩니다. 루프의 블록이 끝나면 루프 변수에 더 이상 액세스할 수 없습니다.
for...range 루프에서 루프 변수는 루프가 반복될 때마다 새 값으로 초기화됩니다. 그러나 루프 내에서 생성된 클로저는 원래 루프 변수를 계속 참조합니다. 클로저에 루프 변수의 독립적인 복사본이 있는지 확인하려면 클로저 내의 지역 변수에 할당해야 합니다.
코드 예
아래는 예입니다. 이는 루프 변수 복사의 필요성을 보여줍니다.
func main() { m := make(map[int32]int32) for i := int32(1); i <= 10; i++ { m[i] = i } l := make([]func() (int32, int32), 0) for k, v := range m { l = append(l, func() (int32, int32) { return k, v }) } for _, f := range l { k, v := f() fmt.Println(k, v) } }
이 예에서 루프 변수 k는 각 반복 중에 변경될 것으로 예상됩니다. for...범위 루프. 그러나 클로저는 루프 전체에서 동일하게 유지되는 원래 루프 변수 k를 캡처합니다. 결과적으로 코드는 동일한 값 쌍(10, 10)을 10번 인쇄합니다.
해결책: 루프 변수 복사
문제를 해결하려면 루프 변수는 클로저 내의 지역 변수에 복사되어야 합니다.
func main() { m := make(map[int32]int32) for i := int32(1); i <= 10; i++ { m[i] = i } l := make([]func() (int32, int32), 0) for k, v := range m { kLocal, vLocal := k, v l = append(l, func() (int32, int32) { return kLocal, vLocal }) } for _, f := range l { k, v := f() fmt.Println(k, v) } }
이제 클로저는 지역 변수를 캡처합니다. for...range 루프의 각 반복 중에 할당된 값을 독립적으로 보유하는 kLocal 및 vLocal. 코드는 예상되는 값 쌍(1, 1), (2, 2), ..., (10, 10)을 올바르게 인쇄합니다.
위 내용은 Go에서 클로저의 루프 변수를 명시적으로 복사해야 하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!