레슨 4 / 8·20분
에러 처리 패턴
Go의 에러 처리 철학
Go는 예외(exception) 대신 에러 값을 반환하는 방식을 사용합니다. 함수가 에러를 반환하면 호출자가 명시적으로 처리해야 합니다. 이 방식은 에러 처리를 강제하여 더 안정적인 코드를 만듭니다.
go
package main
import (
"errors"
"fmt"
"strconv"
)
// 에러를 반환하는 함수
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("0으로 나눌 수 없습니다")
}
return a / b, nil
}
func main() {
// 기본 에러 처리 패턴
result, err := divide(10, 3)
if err != nil {
fmt.Println("에러:", err)
return
}
fmt.Printf("결과: %.2f\n", result)
// 에러 발생 시
_, err = divide(10, 0)
if err != nil {
fmt.Println("에러:", err) // 에러: 0으로 나눌 수 없습니다
}
// 표준 라이브러리의 에러 처리
num, err := strconv.Atoi("abc")
if err != nil {
fmt.Println("변환 에러:", err)
} else {
fmt.Println("숫자:", num)
}
}커스텀 에러 타입
error 인터페이스를 구현하면 커스텀 에러 타입을 만들 수 있습니다. 에러에 추가 정보를 담아 더 풍부한 에러 처리가 가능합니다.
go
package main
import (
"errors"
"fmt"
)
// 커스텀 에러 타입
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("필드 %s: %s", e.Field, e.Message)
}
func validateAge(age int) error {
if age < 0 || age > 150 {
return &ValidationError{
Field: "age",
Message: "유효하지 않은 나이입니다",
}
}
return nil
}
// 에러 래핑 (Go 1.13+)
func processUser(age int) error {
err := validateAge(age)
if err != nil {
return fmt.Errorf("사용자 처리 실패: %w", err)
}
return nil
}
func main() {
err := processUser(200)
if err != nil {
fmt.Println(err) // 사용자 처리 실패: 필드 age: 유효하지 않은 나이입니다
// errors.As로 원본 에러 타입 확인
var valErr *ValidationError
if errors.As(err, &valErr) {
fmt.Println("필드:", valErr.Field)
}
}
}defer, panic, recover
go
package main
import "fmt"
// defer - 함수 종료 시 실행 (LIFO 순서)
func fileExample() {
fmt.Println("파일 열기")
defer fmt.Println("파일 닫기") // 함수 끝에서 실행
fmt.Println("파일 작업 중...")
// 출력: 파일 열기 -> 파일 작업 중... -> 파일 닫기
}
// panic과 recover
func safeDivide(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("패닉 복구: %v", r)
}
}()
return a / b, nil // b=0이면 panic 발생
}
func main() {
fileExample()
result, err := safeDivide(10, 0)
if err != nil {
fmt.Println(err) // 패닉 복구: runtime error: ...
} else {
fmt.Println(result)
}
}- •
error-- Go의 에러 인터페이스 (Error() string) - •
errors.New()-- 단순 에러 생성 - •
fmt.Errorf("%w", err)-- 에러 래핑 - •
errors.Is()-- 에러 값 비교 - •
errors.As()-- 에러 타입 변환 - •
defer-- 함수 종료 시 실행할 코드 예약
💡
Go에서 panic은 프로그램 버그와 같은 복구 불가능한 상황에서만 사용하세요. 일반적인 에러는 항상 error 값으로 반환하는 것이 관례입니다.