Go에서 클로저 캡처를 연기하면 예기치 않은 동작이 발생하는 이유는 무엇입니까?

Linda Hamilton
풀어 주다: 2024-11-10 19:35:02
원래의
471명이 탐색했습니다.

Why Does Deferring Closure Capture in Go Lead to Unexpected Behavior?

Go에서 클로저 캡처 연기

Go의 defer 문을 사용하면 주변 함수가 반환된 후 함수를 실행할 수 있습니다. 그러나 클로저와 함께 사용할 경우 매개변수 캡처가 어떻게 작동하는지 이해하는 것이 중요합니다.

문제

다음 코드를 고려하세요.

package main

import "fmt"

func main() {
    var whatever [5]struct{}

    for i := range whatever {
        fmt.Println(i)
    } // part 1

    for i := range whatever {
        defer func() { fmt.Println(i) }()
    } // part 2

    for i := range whatever {
        defer func(n int) { fmt.Println(n) }(i)
    } // part 3
}
로그인 후 복사

코드의 출력 is:

0
1
2
3
4
4
3
2
1
0
4
4
4
4
4
로그인 후 복사

분석

  • 1부: 루프 카운터 i를 예상대로 인쇄합니다.
  • 파트 2: 클로저에서 변수 i를 캡처합니다. 그러나 클로저가 실행되면 i는 루프의 마지막 반복에서 얻은 값인 4를 갖게 됩니다. 따라서 "44444"가 인쇄됩니다.
  • 3부: 캡처하지 않습니다. 모든 외부 변수. defer 문이 실행될 때 클로저가 평가되므로 각 defer 호출은 서로 다른 n 값을 가지며 결과적으로 "43210"이 됩니다.

주요 차이점

파트 2와 파트 3의 결정적인 차이점은 클로저가 외부 변수를 포착하는지 여부에 있습니다. 파트 2에서 클로저는 외부 변수에 대한 참조인 i를 캡처합니다. 3부에서는 클로저에 외부 참조가 없으므로 각 호출마다 서로 다른 n 값을 갖습니다.

추가 고려 사항

  • Defer 호출은 다음과 같습니다. 주변 함수가 반환되기 전에 LIFO(후입선출) 순서로 실행됩니다.
  • defer 문이 실행될 때 평가되는 표현식 함수 자체가 아니라 실행됩니다.

위 내용은 Go에서 클로저 캡처를 연기하면 예기치 않은 동작이 발생하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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