티스토리 뷰

Go

panic() 과 recover()

LichKing 2019. 3. 1. 20:06

go에서 기본적으로 제공하는 함수로 panic()과 recover()가 있다. 단순 콘솔 출력해도 fmt 패키지를 임포트해야하는 go인데 저 두 함수는 아무것도 임포트할필요없이 곧바로 제공하고있다.


함수명에서부터 알 수 있듯이 panic()은 go 실행 루틴을 패닉에 빠지게하고(강제종료) recover()는 그걸 복구하는 역할을 한다. 간단한 예제를 살펴보자.


func main() {
fmt.Println("hello")

panic("happen panic!")

fmt.Println("goodbye")
}


panic() 이 실행되면서 실행 루틴이 종료되기때문에 goodbye는 출력되지 않는다.

recover() 를 이용해서 복구시켜보자.


func main() {
fmt.Println("hello")

panic("happen panic!")
recover()

fmt.Println("goodbye")
}


참고로 이런코드는 의도한대로 동작하지않는다. panic() 이 실행되면서 바로 끝나기때문에 recover() 가 실행될 수 없다. 앞선 포스팅에서 소개한 defer를 이용해야한다.


func main() {
fmt.Println("hello")

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

panic("happen panic!")

fmt.Println("goodbye")
}


처음엔 defer recover() 라고 코드를 작성했었는데 IDE가 저렇게 바꾸라고한다. 저 형태가 베스트 프랙티스인가보다.(참고로 IDE는 goland를 이용하고있다.)


코드를 돌려보면 알겠지만 goodbye는 여전히 출력되지않는다. 단지 panic() 으로 인한 에러 로그가 출력되지않고 정상종료될뿐이다. 지금은 단순 예제로 main() 함수만 있는 형태라서 그냥 프로세스가 종료되는 형태라 알아보기힘들지만 panic() 이 호출되면 recover() 로 살리더라도 이미 그 함수는 종료되어버리게된다. 아래 예제로 조금 더 이해해보자.


func main() {
fmt.Println("hello")

panicAndRecover()

fmt.Println("goodbye")
}

func panicAndRecover() {
defer func() {
if r := recover(); r != nil {
fmt.Println("recover!")
}
}()

panic("happen panic!")

fmt.Println("T.T")
}


이경우엔 panicAndRecover() 가 종료되면서 recover() 로 복구됐기때문에 main() 함수 스택은 정상적으로 goodbye를 출력한다.


panic() 과 recover() 를 자바의 UncheckedException 같다라는 느낌이 들긴하는데.. 이런용도로 사용하는지는 다른 코드들을 좀 더 봐봐야겠다.

'Go' 카테고리의 다른 글

goroutine  (0) 2019.03.28
command line argument 받기  (0) 2019.03.23
array와 slice  (0) 2019.03.02
panic() 과 recover()  (0) 2019.03.01
defer 키워드  (0) 2019.03.01
댓글
댓글쓰기 폼