사용자 지정 오류 만들기
errors.New, fmt.Errorf 및 센티널 오류
사용자 지정 오류 만들기은(는) CoddyKit의 무료 Go Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Go Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
사용자 지정 오류 타입이 필요한 이유
사용자 지정 오류 타입은 문자열 메시지를 넘어 구조화된 데이터를 전달하므로, 호출자가 특정 오류 상태를 검사하고 그에 따라 대응할 수 있습니다:
package main
import "fmt"
// Custom error type carries extra context
type HTTPError struct {
StatusCode int
Message string
}
func (e *HTTPError) Error() string {
return fmt.Sprintf("HTTP %d: %s", e.StatusCode, e.Message)
}
func fetch(url string) error {
return &HTTPError{404, "page not found"}
}
func main() {
err := fetch("http://example.com")
fmt.Println(err) // HTTP 404: page not found
}error 인터페이스 구현
Error() string 메서드를 가진 모든 타입은 error를 충족합니다:
package main
import "fmt"
type ValidationError struct {
Field string
Value interface{}
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation: field %q value %v — %s", e.Field, e.Value, e.Message)
}
func validateAge(age int) error {
if age < 0 || age > 150 {
return &ValidationError{"age", age, "must be between 0 and 150"}
}
return nil
}
func main() {
fmt.Println(validateAge(-5))
}errors.New를 사용한 센티널 오류
센티널 오류는 잘 알려진 오류 상태를 나타내는 패키지 수준 변수입니다:
package main
import ("fmt"; "errors")
var (
ErrNotFound = errors.New("not found")
ErrUnauthorized = errors.New("unauthorized")
ErrAlreadyExists = errors.New("already exists")
)
func getUser(id int) (string, error) {
if id != 1 { return "", ErrNotFound }
return "Alice", nil
}
func main() {
_, err := getUser(99)
if errors.Is(err, ErrNotFound) {
fmt.Println("user does not exist")
}
}래핑을 위한 %w를 사용한 fmt.Errorf
%w와 함께 사용하는 fmt.Errorf는 오류를 래핑하면서 원래 오류를 보존하므로 errors.Is와 errors.As에서 사용할 수 있습니다:
package main
import ("fmt"; "errors")
var ErrDatabase = errors.New("database error")
func queryDB() error {
return fmt.Errorf("queryDB: %w", ErrDatabase)
}
func main() {
err := queryDB()
fmt.Println(err) // queryDB: database error
fmt.Println(errors.Is(err, ErrDatabase)) // true — unwrapped
}Unwrap을 사용한 사용자 지정 오류
사용자 지정 오류 타입에 Unwrap() error를 구현하면 오류 체인에 참여할 수 있습니다:
package main
import ("fmt"; "errors")
var ErrNotFound = errors.New("not found")
type QueryError struct {
Query string
Err error
}
func (e *QueryError) Error() string {
return fmt.Sprintf("query %q: %v", e.Query, e.Err)
}
func (e *QueryError) Unwrap() error { return e.Err }
func main() {
err := &QueryError{"SELECT *", ErrNotFound}
fmt.Println(err)
fmt.Println(errors.Is(err, ErrNotFound)) // true
}errors.Is — 동일성 확인
errors.Is는 대상과 같은 오류를 찾을 때까지 오류 체인을 탐색합니다:
package main
import ("fmt"; "errors")
var ErrTimeout = errors.New("timeout")
func deepCall() error {
return fmt.Errorf("layer3: %w", fmt.Errorf("layer2: %w", ErrTimeout))
}
func main() {
err := deepCall()
fmt.Println(errors.Is(err, ErrTimeout)) // true — found deep in chain
}errors.As — 타입 추출
errors.As는 대상 타입과 일치하는 체인의 첫 번째 오류를 찾아 할당합니다:
package main
import ("fmt"; "errors")
type PermissionError struct{ User string }
func (e *PermissionError) Error() string { return "permission denied for " + e.User }
func action(user string) error {
return fmt.Errorf("action: %w", &PermissionError{user})
}
func main() {
err := action("bob")
var pe *PermissionError
if errors.As(err, &pe) {
fmt.Println("denied:", pe.User) // denied: bob
}
}여러 오류 래핑(Go 1.20 이상)
Go 1.20에서는 오류를 결합하기 위한 errors.Join과 여러 %w를 지원하는 fmt.Errorf가 추가되었습니다:
package main
import ("fmt"; "errors")
func validate(name, email string) error {
var errs []error
if name == "" { errs = append(errs, errors.New("name required")) }
if email == "" { errs = append(errs, errors.New("email required")) }
return errors.Join(errs...)
}
func main() {
err := validate("", "")
fmt.Println(err)
// name required
// email required
}오류 타입 명명 규칙
Go에서 오류 변수와 타입을 명명하는 규칙은 다음과 같습니다:
- 센티널 오류 변수:
ErrXxx(예:ErrNotFound) - 사용자 지정 오류 타입:
XxxError(예:ValidationError) - 센티널에는 패키지 수준 var를, 풍부한 오류에는 포인터 타입을 사용합니다
- 호출자가
errors.Is또는errors.As에서 사용할 수 있도록 내보냅니다
각 접근 방식을 사용하는 경우
적절한 오류 접근 방식 선택:
errors.New— 추가 데이터가 없는 단순 오류 및 센티널 동일성 확인fmt.Errorf— 선택적 래핑이 가능한 형식 지정 메시지- 사용자 지정 타입 — 호출자에게 구조화된 데이터(필드, 코드)가 필요할 때
errors.Join— 여러 유효성 검사 오류를 집계할 때
빠른 확인
오류 체인에서 특정 오류 타입을 추출할 수 있는 함수는 무엇인가요?
복습: 사용자 지정 오류
요약:
Error() string을 구현하여 사용자 지정 오류 타입을 만듭니다Unwrap() error를 추가하여 오류 체인에 참여시킵니다- 동일성 확인에는
errors.Is를, 타입 추출에는errors.As를 사용합니다 - 센티널 오류:
ErrXxx, 사용자 지정 타입:XxxError errors.Join은 여러 오류를 집계합니다(Go 1.20 이상)
자주 묻는 질문
“사용자 지정 오류 만들기” 강의는 무료인가요?
네 — “사용자 지정 오류 만들기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Go Academy 강의 전체를 잠금 해제할 수 있습니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“사용자 지정 오류 만들기”에서 뭘 배우나요?
errors.New, fmt.Errorf 및 센티널 오류 브라우저에서 직접 실행하는 실습 코드로 Go Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Go Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Go Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“사용자 지정 오류 만들기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Go Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Go Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- error 인터페이스
- 사용자 지정 오류 만들기
- 오류 래핑과 언래핑
- panic, recover 및 defer