"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > Go의 사용자 정의 오류

Go의 사용자 정의 오류

2024-11-08에 게시됨
검색:147

Custom errors in Go

소개

Golang 또는 Go에는 언어 설계에 필수적인 강력한 오류 처리 메커니즘이 있습니다. Go는 기본 제공 오류 유형을 제공하지만 오류 처리에 더 많은 제어와 컨텍스트가 필요할 수 있는 상황이 있습니다.
여기서 사용자 정의 오류가 발생합니다. 사용자 정의 오류는 더 많은 정보를 제공하는 오류 메시지를 제공할 수 있으며 애플리케이션의 다양한 오류 유형을 분류하는 데 사용될 수 있습니다.

이 글에서는 Golang에서 사용자 정의 오류를 효과적으로 생성하고 사용하는 방법을 살펴보겠습니다.

Go에 내장된 오류 처리 이해하기

Go에서 오류 유형은 다음과 같은 내장 인터페이스입니다.

type error interface {
    Error() string
}

문자열 반환 유형으로 Error() 메서드를 구현하는 모든 유형은 이 인터페이스를 만족하며 오류로 간주될 수 있습니다. 이 메서드를 구현하기만 하면 사용자 정의 오류 유형을 만들 수 있으므로 간단하지만 강력합니다.

Go의 기본 오류 처리

다음은 Go의 기본 오류 처리에 대한 간단한 예입니다.

package main

import (
    "errors"
    "fmt"
)

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println("Error:", err)
    }
}

func doSomething() error {
    return errors.New("something went wrong")
}

이 예에서는 error.New 함수를 사용하여 기본 오류를 생성합니다. 이는 간단한 경우에 유용하지만 더 많은 컨텍스트를 제공하거나 다양한 유형의 오류를 구별하는 기능이 부족합니다.

사용자 정의 오류를 만드는 이유는 무엇입니까?

더 자세한 오류 메시지가 필요하거나 다양한 유형의 오류를 다르게 처리하려는 경우 사용자 정의 오류가 필수적입니다. 예를 들어, 파일을 찾을 수 없으면 특정 오류 유형을 반환하고, 파일이 손상되면 다른 유형을 반환하려고 할 수 있습니다. 사용자 정의 오류는 추가 데이터를 전달할 수도 있으므로 디버깅이 더 쉬워지고 호출자에게 더 자세한 정보가 제공됩니다.

Go에서 사용자 정의 오류 만들기

Go에서 사용자 정의 오류를 생성하려면 Error() 메소드를 구현하는 새로운 유형을 정의합니다. 예시를 살펴보겠습니다.

예 1: 간단한 사용자 정의 오류

간단한 사용자 정의 오류를 만드는 방법은 다음과 같습니다.

package main

import (
    "fmt"
)

type MyError struct {
    Code    int
    Message string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("Code %d: %s", e.Code, e.Message)
}

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println("Error:", err)
    }
}

func doSomething() error {
    return &MyError{
        Code:    404,
        Message: "Resource not found",
    }
}

이 예에서 MyError는 코드와 메시지를 포함하는 사용자 정의 오류 유형입니다. Error() 메서드는 이를 문자열로 형식화하여 오류를 쉽게 인쇄하거나 기록할 수 있도록 합니다.

예시 2: 오류로 오류 확인.Is 함수

때로는 오류를 직접 비교하는 것이 유용할 수 있습니다. 여기서 센티널 오류가 발생합니다. 센티널 오류는 특정 오류를 나타내는 미리 정의되고 내보낸 변수입니다.

package main

import (
    "errors"
    "fmt"
)

var ErrNotFound = errors.New("resource not found")

func main() {
    err := doSomething()
    if errors.Is(err, ErrNotFound) {
        fmt.Println("Error:", err)
    }
}

func doSomething() error {
    return ErrNotFound
}

이 접근 방식은 간단하지만 센티널 값을 사용자 정의 오류 유형과 결합하면 오류 비교와 풍부한 오류 데이터가 모두 허용되므로 더욱 강력해질 수 있습니다.

예 3: 추가 컨텍스트를 위해 오류 래핑

Go 1.13에는 %w 동사가 포함된 fmt.Errorf 함수가 도입되었습니다. 이를 통해 오류를 래핑하고 원래 오류를 유지하면서 더 많은 컨텍스트를 추가할 수 있습니다.

package main

import (
    "errors"
    "fmt"
)

var ErrNotFound = errors.New("resource not found")

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println("Error:", err)
        if errors.Is(err, ErrNotFound) {
            fmt.Println("The resource was not found.")
        }
    }
}

func doSomething() error {
    err := fetchResource()
    if err != nil {
        return fmt.Errorf("failed to do something: %w", err)
    }
    return nil
}

func fetchResource() error {
    return ErrNotFound
}

이를 통해 특정 오류를 확인하고 무엇이 잘못되었는지에 대한 더 많은 컨텍스트를 제공하는 오류 스택을 유지할 수도 있습니다.

예제 4: Unwrap() 메서드를 사용하여 오류 강화

Go는 Unwrap() 메서드를 사용하여 래핑된 오류를 추출하는 방법도 제공합니다. 사용자 정의 오류 유형에 이 방법을 구현하면 오류를 추가로 풀 수 있습니다.

package main

import (
    "errors"
    "fmt"
)

type MyError struct {
    Code    int
    Message string
    Err     error
}

func (e *MyError) Error() string {
    return fmt.Sprintf("Code %d: %s", e.Code, e.Message)
}

func (e *MyError) Unwrap() error {
    return e.Err
}

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println("Error:", err)
        if errors.Is(err, ErrNotFound) {
            fmt.Println("The resource was not found.")
        }
    }
}

var ErrNotFound = errors.New("resource not found")

func doSomething() error {
    err := fetchResource()
    if err != nil {
        return &MyError{
            Code:    500,
            Message: "Something went wrong",
            Err:     err,
        }
    }
    return nil
}

func fetchResource() error {
    return ErrNotFound
}

여기서 MyError에는 래핑된 오류를 반환하는 Unwrap() 메서드가 있습니다. 이를 통해 근본적인 오류를 더 자세히 검사하고 처리할 수 있습니다.

예제 5: 오류가 있는 오류 확인.As 함수

Go는 오류가 있는 오류를 추출하는 방법도 제공합니다. 사용자 정의 오류 유형에 이 메소드를 구현하면 오류 유형을 확인하고 사용자 정의 오류 값을 가져올 수도 있습니다.

package main

import (
    "errors"
    "fmt"
)

type MyError struct {
    Code    int
    Message string
    Err     error
}

func (e *MyError) Error() string {
    return fmt.Sprintf("Code %d: %s: %v", e.Code, e.Message, e.Err)
}

func main() {
    err := doSomething()
    var mErr *MyError
    // another way to initialize custom error
    // mErr := &MyError{}
    if errors.As(err, &mErr) {
        fmt.Println("Error:", mErr)
    }
}

// doSomething attempts to fetch a resource and returns an error if it fails.
// If the error is ErrNotFound, it is wrapped in a MyError with a code of 500.
func doSomething() error {
    err := fetchResource()
    if err != nil {
        return &MyError{
            Code:    500,
            Message: "Something went wrong",
            Err:     err,
        }
    }
    return nil
}

var ErrNotFound = errors.New("resource not found")

func fetchResource() error {
    return ErrNotFound
}

Go의 사용자 정의 오류에 대한 모범 사례

  1. 사용자 정의 오류를 드물게 사용하십시오: 사용자 정의 오류는 강력하지만 복잡성을 가중시킬 수 있습니다. 더 나은 오류 분류 또는 추가 컨텍스트와 같은 중요한 이점을 제공하는 경우 이를 사용하십시오.

  2. 래핑 및 언래핑 활용: 추가 컨텍스트로 오류를 래핑하고 나중에 언래핑하는 것은 오류 디버깅을 향상시키는 모범 사례입니다.

  3. 오류 유형을 문서화하세요: 모든 사용자 정의 오류는 해당 목적과 사용법이 명확하도록 잘 문서화되어 있는지 확인하세요.

  4. 비교를 위해 오류 값 선호: 오류를 비교해야 하는 경우 일관성과 명확성을 위해 사전 정의된 오류 값(센티넬 오류) 사용을 고려하세요.

결론

Go의 사용자 정의 오류는 애플리케이션의 오류를 관리하는 유연하고 강력한 방법을 제공합니다. 고유한 오류 유형을 생성하고, 추가 컨텍스트를 위해 오류를 래핑하고, 심층적인 검사를 위해 래핑을 해제함으로써 강력하고 유지 관리가 가능한 오류 처리 메커니즘을 구축할 수 있습니다. 이는 디버깅에 도움이 될 뿐만 아니라 Go 코드의 전반적인 품질도 향상시킵니다.
오류가 있는 전략을 선택하고 전체 프로젝트에서 일관된 오류를 사용하십시오.

릴리스 선언문 이 글은 https://dev.to/ankitmalikg/create-custom-errors-in-golang-3mdl?1에서 복제됩니다.1 침해 내용이 있는 경우, [email protected]으로 연락하여 삭제하시기 바랍니다.
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3