본문 바로가기

golang

[golang] defer, panic, recover

golang에는 try~ catch역할을 할 수 있는 기능을 defer, panic, recover type으로 제공한다.

 

1. defer

defer는 함수의 마지막에 호출할 수 있도록 stack에 해당 라인을 추가한다. (stack으로 추가되니 여러개의 defer가 있는 경우 LIFO(Last In First Out)으로 실행)
예를 들어 file 입출력을 할 때, file Open 이후 바로 defer close() 와 같이 선언하여 함수 종료 후 file을 close 할 수 있게된다.

만약 함수 실행 중 에러로 인해 비정상 종료되는 경우에도 defer 실행 후 종료되는데, 이 때 발생한 에러보다 이전에 defer가 수행되어 있어야 한다. 

 

2. panic

go 프로그램 실행 도중 에러로 인해 프로그램이 비정상 종료되는 경우 'panic이 발생했다' 라고 하는데, 비정상 상황 외에도 사용자가 의도적으로 panic 함수를 실행하여 비정상 종료를 시킬 수 있다. 

 

3. recover

위와 같이 panic으로 인하여 비정상 종료할 때, recover 함수를 이용하여 복구 할 수 있다. 쉽게 말해 panic 상황 발생하였을 때, 프로그램을 종료하지 않고 에러로 처리할 수 있게된다.

 

위에서 다룬 defer, panic, recover를 조합하여 안정적인 프로그램을 작성할 수 있다.

package main

import "fmt"

func averageAge() float64{	
	var num int
	fmt.Scanln(&num)
	
	if num <= 0 {
		panic("잘못된 인원 수 입니다.")
	}
	
	
	var age, sum int
	
	for i := 0; i < num; i++ {
		fmt.Scanln(&age)
		
		if age < 0 {
			panic("잘못된 나이입니다.")
		}
		
		
		sum += age
		
	}
	
	avg := float64(sum) / float64(num)
	
	return avg
}


func main() {
	defer func() {
		if r := recover(); r != nil{
			fmt.Println(r)
			main()
		}
	}()
	
	result := averageAge()	
	fmt.Println(result)	
}

여러 사람의 나이 평균을 구하는 프로그램이다.
유저로부터 잘못된 입력값을 받은 경우 panic을 호출하여 비정상으로 프로그램을 종료할 수 있다.

main() 함수에는 defer로 함수가 호출되어 있는데, main 함수 종료시마다 호출될 것이며 만약 recover가 nil이 아니라면, 즉 비정상적으로 프로그램이 종료된 경우 error msg 출력과 함께 main 함수를 재시작한다.

 

defer func() {}() 의 경우 마지막 () 이 빠지면 "expression in defer must be function call" 에러가 출력된다. defer가 만약 없다면, ()가 없어도 error없이 실행될 수 있는데 그렇게되면 func의 return value가 아닌 func value를 갖게 되는 것이다. defer를 사용하는 경우에는 mandatory로 ()를 사용하도록 명시되어있다.

* ()를 붙임으로서 함수를 호출하는것을 의미, defer를 했음에도 호출하지 않는것은 syntax error로 인지하는것으로 이해
https://stackoverflow.com/questions/16008604/why-add-after-closure-body-in-golang
반응형