Go의 defer는 함수가 끝나기 직전에 실행됩니다. 다만 실행을 미룬다고 해서 값까지 나중에 정해지는 것은 아닙니다. 일반 함수 호출의 인자는 defer를 만난 순간 계산되고, 클로저 본문은 실제로 실행될 때 변수를 읽습니다.
같은 변수, 다른 결과
gomain.go
package main
import "fmt"
func main() {
name := "first"
defer fmt.Println("1:", name)
name = "second"
defer func() {
fmt.Println("2:", name)
}()
name = "third"
}실행 결과는 다음과 같습니다.
text
2: third
1: firstfmt.Println("1:", name)의 인자는 defer가 등록될 때 평가됩니다. 이때 name은 "first"이므로, 이후 변수를 바꿔도 저장된 값은 달라지지 않습니다.
두 번째 defer는 익명 함수의 실행만 미룹니다. 함수 본문에서 name을 읽는 시점에는 이미 값이 "third"로 바뀐 뒤입니다. 두 출력의 순서가 뒤집힌 이유는 나중에 등록한 defer부터 실행되기 때문입니다.
값을 지금 고정하려면
클로저에서도 현재 값을 기억하게 하려면 인자로 넘기면 됩니다.
go
defer func(saved string) {
fmt.Println(saved)
}(name)여기서 name은 defer를 등록하는 순간 saved에 전달됩니다. defer 안에서 바깥 변수를 바로 참조하는지, 인자로 넘기는지만 구분하면 실행 결과를 예상하기 쉬워집니다.