Defer-(2)
defer의 실행 순서
defer는 코드의 실행 순서에 관여하는 기능이니만큼 규칙을 확실하게 인지하고 있어야한다.
- 기본적으로 defer는 선언된 역순으로 실행되는 Stack형식이다.
- 현재 코드 블록을 빠저나가기 전에 실행된다.
func Print() {
defer {
print("첫번째 defer")
}
defer {
print("두번째 defer")
}
defer {
print("세번째 defer")
}
defer {
print("네번째 defer")
}
defer {
print("다섯번째 defer")
}
defer {
print("여섯번째 defer")
}
}
역순으로 실행되기 때문에 위 예제 코드를 실행시 아래와 같은 결과를 확인할 수 있다.
여섯번째 defer
다섯번째 defer
네번째 defer
세번째 defer
두번째 defer
첫번째 defer
중첩 코드 블럭에서의 defer 실행 순서
다음은 조금 더 복잡한 중첩 코드 블럭에서의 예제를 살펴보자.
func test() {
defer {
print("test 1")
}
for i in 0..<2 {
defer {
print("test 2")
}
if i % 2 == 0 {
defer {
print("test 3")
}
print("test 4")
}
}
defer {
print("test 5")
}
print("test 6")
}
위 코드의 결과는 아래와 같다.
test 4
test 3
test 2
test 2
test 6
test 5
test 1
블럭 단위로 끊어보면 이해하기 쉽다.
- 맨 먼저 가장 안쪽에 있는 if문 코드 블럭이 가장 먼저 끝나기 때문에 그 안에 있는 defer가 먼저 출력된다. 따라서 test 4를 출력하고 코드 블럭이 끝나기 직전에 test 3을 출력한다.
- 다음으로는 for문 코드 블럭이 끝난다. 따라서 쌓여있던 test 2가 두번 출럭된다.
- 마지막으로 끝나는 test()의 코드 블럭의 test 6을 출력한 뒤 순서대로 쌓여있던 test 1와 test 6이 역순으로 출력된다.
Defer가 호출되지 않는 경우
defer가 스택에 담기기 전에 코드 블럭이 종료되면 이후의 defer는 호출되지 않는다.
func test() {
defer {
print("test 1")
}
return
defer {
print("test 2")
}
}
위 예제에서는 첫번째 defer가 스택에 쌓이고 바로 함수가 종료된다.
따라서 두번째 defer는 스택에 쌓이지 않게 되기 때문에 test 1만 출력된다.
이 외에도 throw로 오류를 발생시키거나 guard문으로 함수가 종료되도 똑같이 이후의 defer는 호출되지 않는다.
참고자료