>  기사  >  백엔드 개발  >  Go에서 `defer func() { fmt.Println(i) }()`가 '44444'를 인쇄하는 반면, `defer func(n int) { fmt.Println(n) }(i)`는 '43210'을 올바르게 인쇄하는 이유는 무엇입니까? ?

Go에서 `defer func() { fmt.Println(i) }()`가 '44444'를 인쇄하는 반면, `defer func(n int) { fmt.Println(n) }(i)`는 '43210'을 올바르게 인쇄하는 이유는 무엇입니까? ?

DDD
DDD원래의
2024-11-10 18:54:02452검색

Why does `defer func() { fmt.Println(i) }()` print

지연 함수 호출 및 클로저 캡처

Go에서 defer 문을 사용하면 주변 함수가 반환되기 직전에 함수를 실행할 수 있습니다. 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
    }
}

1부에서는 단순히 i 값을 0에서 4까지 인쇄합니다. 그러나 2부에서는 다음을 보여줍니다. 흥미로운 행동이다. 0~4의 예상 값을 인쇄하는 대신 "44444"를 출력합니다.

이는 파트 2의 클로저가 i 변수를 캡처하기 때문입니다. 나중에 클로저가 실행되면 i 변수는 range 문의 마지막 반복에서 가졌던 값인 4를 갖게 됩니다. 결과적으로 모든 지연된 함수 호출은 4를 인쇄합니다.

반대로, 부분 3은 외부 변수를 캡처하지 않습니다. Go 사양에 따르면 "'defer' 문이 실행될 때마다 호출에 대한 함수 값과 매개 변수가 평소와 같이 평가되어 새로 저장되지만 실제 함수는 호출되지 않습니다." 이는 각각의 지연된 함수 호출이 'n' 매개변수의 서로 다른 값을 갖는다는 것을 의미하며, 이는 'defer' 문이 실행될 당시의 'i' 값입니다.

따라서 3부를 올바르게 주변 함수가 반환되기 전에 지연된 함수 호출이 LIFO 순서(후입선출)로 실행되므로 "43210"을 인쇄합니다.

'defer f()'의 함수 표현식을 기억하는 것이 중요합니다. defer 문이 실행되는 시점에는 실행되지 않지만 'defer f(e)'의 표현식은 즉시 평가됩니다.

위 내용은 Go에서 `defer func() { fmt.Println(i) }()`가 '44444'를 인쇄하는 반면, `defer func(n int) { fmt.Println(n) }(i)`는 '43210'을 올바르게 인쇄하는 이유는 무엇입니까? ?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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