[Go]

[Go] 고랭에서의 예외처리 (exception handling in golang)

dogfootman 2024. 6. 22. 00:38

개요

예외 처리:

많은 언어에서 예외는 프로그램 실행 중에 발생하는 비정상적인 상황을 처리하기 위한 메커니즘

예외는 try-catch 블록을 사용하여 처리

 

패닉 처리:

Go 언어에서는 패닉은 프로그램이 정상적으로 계속 실행될 수 없는 심각한 오류가 발생했을 때 사용

패닉이 발생하면 현재 고루틴은 즉시 중단되고, defer로 등록된 함수들이 호출된 후 프로그램이 종료

recover를 사용하여 패닉을 복구할 수 있지만, 일반적인 오류 처리 메커니즘으로 사용되지는 않음

 

 

 

1. panic이 발생하는 프로그램

package main

import "fmt"

func main() {
    fmt.Println("Start!!")
    divide(10, 0)
    fmt.Println("End")
}

func divide(x, y int) int {
    return x / y
}

 

 

0으로 나누어 패닉을 발생 시킨다.

  1. main 함수에서 시작 메세지를 출력
  2. divide 함수를 호출
  3. y에 0을 전달 했기때문에 panic이 발생
  4. 종료메세지는 실행 되지 않는다.

 

실행 결과: 

Start!!
panic: runtime error: integer divide by zero

goroutine 1 [running]:
main.divide(...)
	D:/Study/golang/project/panic/main.go:12
main.main()
	D:/Study/golang/project/panic/main.go:7 +0x52

 

 

 

2. recovery를 추가한 프로그램

package main

import "fmt"

func main() {
    fmt.Println("Start!!")
    divide(10, 0)
    fmt.Println("End!!")
}

func divide(x, y int) {
    defer func() {
       if r := recover(); r != nil {
          fmt.Println("Recovery: ", r)
       }
    }()

    fmt.Println("Start divide: ", x, y)
    result := x / y
    fmt.Println("Result: ", result)
}

 

divide의 첫줄에 defer func을 추가

  1. main 함수에서 시작 메세지를 출력
  2. divide 함수를 호출
  3. y에 0을 전달 했기때문에 panic이 발생
  4. func 실행이 종료되었으므로 defer의 func이 실행
  5. recovery가 nil이 아니므로 리커버리의 메세지를 출력
  6. Result는 출력되지 않는다.
  7. main 함수에서 종료 메세지가 출력

 

실행 결과: 

Start!!
Start divide:  10 0
Recovery:  runtime error: integer divide by zero
End!!

 

 

 

3. error를 반환하여 처리한 프로그램

package main

import (
    "errors"
    "fmt"
)

func main() {
    fmt.Println("Start!!")
    result, err := divide(10, 0)
    if err != nil {
       fmt.Println("Error:", err)
    } else {
       fmt.Println("Result:", result)
    }
    fmt.Println("End!!")
}

func divide(x, y int) (int, error) {
    if y == 0 {
       return 0, errors.New("cannot divide by zero")
    }
    return x / y, nil
}

 

y이 0이 전달 될 경우 panic이 발생 할 것이 예측 가능하므로 명시적으로 error를 반환

  1. main 함수에서 시작 메세지를 출력
  2. divide 함수를 호출
  3. y에 0을 전달 되었기 때문에 error를 명시적으로 반환
  4. main 함수에서 err가 있으면 에러 메세지를 출력, 없으면 결과 값을 출력
  5. main 함수에서 종료 메세지가 출력

 

실행 결과:

Start!!
Error: cannot divide by zero
End

 

 

 

4. panic recovery나 return error를 사용 할 때 고려 해야 할 사항

패닉을 사용할 때:

  1. 심각한 오류: 패닉은 복구할 수 없는 심각한 오류 상황에서만 사용해야 함
  2. 즉시 중단: 프로그램을 즉시 중단시키므로, recovery를 통해 적절한 처리가 필요
  3. 디버깅: 패닉이 발생한 위치와 원인을 파악하기 쉽도록 패닉 메세지에 대한 정보를 출력

에러를 반환할 때:

  1. 예측 가능한 오류: 예상할 수 있는 오류 상황에서는 에러를 반환하는 것을 우선적으로 고려
  2. 오류 처리: 호출자에게 오류를 알려, 호출자에서  적절한  조치를 취할 수 있도록 함

 

 

 

 

참고:

https://go.dev/blog/defer-panic-and-recover