defer
defer는 함수가 종료될 때 실행한다.
func Test() {
fmt.Println("--Begin--")
defer fmt.Println("111")
defer fmt.Println("222")
defer fmt.Println("333")
fmt.Println("--End--")
/* --Begin--
* --End--
* 333
* 222
* 111
*/
}
defer 문이 '--End--'보다 먼저 선언되었지만 함수 마지막에 실행된다.
defer 문이 여러 개일 때는 stack처럼 동작된다.
panic
panic은 오류가 발생했을 때 프로그램을 중지시키고 defer 문이 실행된다.
func WriteTxt(file, sentence string) {
f, err := os.Create(file)
if err != nil {
panic(err)
}
defer f.Close()
s := []byte(sentence)
f.Write(s)
}
txt 파일에 문장을 작성하는 코드이다. 만약 파일을 생성하는 과정에서 에러가 발생하면 panic을 통해 프로그램을 중지시킨다. 그리고 defer를 실행해 파일을 닫는다.
func panic(v any)
panic에는 어떤 자료형도 전달할 수 있다.
recover
recover은 panic이 발생했을 때 프로그램이 종료되지 않도록 해준다. panic과 recover를 이해하려면 call stack을 살펴봐야 한다.
panic이 발생했다면 recover를 찾을 때까지 call stack을 따라 올라간다. 만약 recover가 있다면 recover를 처리하고, 없다면 프로그램이 종료된다.
자세한 예시는 아래와 같다.
func main() {
fmt.Println("--Start Main--")
f()
fmt.Println("--Finish Main--")
/* --Start Main--
* --Start f--
* Panic occurred: [ Panic in raisePanic()! ]
* --Finish Main--
*/
}
func f() {
fmt.Println("--Start f--")
defer func() {
if r := recover(); r != nil {
fmt.Println("Panic occurred:", r)
}
}()
raisePanic()
fmt.Println("--Finish f--")
}
func raisePanic() {
panic("[ Panic in raisePanic()! ]")
}
위 코드에서 호출 스택은 main > f > raisePanic이다.
그리고 실행 과정은 아래와 같다.
- (main) --Start Main--
- (main) f() 호출
- (f) --Start f--
- (f) raisePanic() 호출
- (raisePanic) panic 발생
- (f) f()로 복귀
- (f) recover에 panic의 인자 전달
- (main) main()으로 복귀
- (main) --Finish Main--
SEH
Go는 'try.. catch', 'try... expect'와 같은 SEH(Structured Exception Handling)을 제공하지 않는다.