어떤 함수를 호출하는 문장 앞에 defer
키워드를 붙이면, 이런 defer문을 담고 있는 함수가 리턴될 때까지 그 함수의 실행을 미룬다.
java나 c#의 finally 구문과 같다
defer문은 파일을 입력 및 출력 연산을 수행할 때 흔히 사용하는데, 이렇게 하면 연 파일을 언제 닫을 지 신경 쓸 필요가 없다.
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
file.WriteString("hello world")
}
defer 문을 담고 있는 함수가 리턴된 후에, defer 키워드를 이용해 실행이 미뤄진 함수가 호출되는 순서는 LIFO
방식을 따른다.
func main() {
defer f1()
defer f2()
defer f3()
}
func f1() {
fmt.Println(1)
}
func f2() {
fmt.Println(2)
}
func f3() {
fmt.Println(3)
}
3
2
1
panic
함수는 Go언어에서 기본으로 제공하는 것으로, 기존 Go 프로그램의 실행 흐름을 종료하고 패닉 상태에 빠진다. recover
함수 역시 Go 언어에서 기본으로 제공하는 것이지만, panic으로 인해 패닉 상태에 빠졌던 Go 루틴으로부터 제어권을 다시 가져온다.
func a() {
fmt.Println("Inside a()")
defer func() {
if c := recover(); c != nil {
fmt.Println("Recover inside a()!")
}
}()
fmt.Println("About to call b()")
b()
fmt.Println("b() exited!")
fmt.Println("Exiting a()")
}
func b() {
fmt.Println("Inside b()")
panic("Panic in b()!")
fmt.Println("Exiting b()")
}
func main() {
a()
fmt.Println("main() ended!")
}