Go에선 명시적으로 별도의 반환값을 통해 에러를 전달하는게 일반적이고 관용적입니다. 익셉션을 사용하는 Java와 Ruby 그리고 때때로 결괏값과 에러값을 단일값에 오버로딩하는 C와는 대조적입니다. Go의 이런 접근법을 통해 어떤 함수가 에러를 반환했는지를 보고 다른 에러 없는 작업에 사용되는 구조체를 사용하여 쉽게 처리할 수 있습니다. |
|
package main
|
|
import "errors"
import "fmt"
|
|
관용적으로, 에러는 마지막 반환값이며 내장 인터페이스인 |
func f1(arg int) (int, error) {
if arg == 42 {
|
|
return -1, errors.New("can't work with 42")
|
}
|
|
에러 위치의 nil값은 에러가 없다는걸 나타냅니다. |
return arg + 3, nil
}
|
|
type argError struct {
arg int
prob string
}
|
func (e *argError) Error() string {
return fmt.Sprintf("%d - %s", e.arg, e.prob)
}
|
|
func f2(arg int) (int, error) {
if arg == 42 {
|
|
이 경우 우리는 |
return -1, &argError{arg, "can't work with it"}
}
return arg + 3, nil
}
|
func main() {
|
|
아래의 두 루프는 에러를 반환하는 각 함수를 테스트합니다.참고로 |
for _, i := range []int{7, 42} {
if r, e := f1(i); e != nil {
fmt.Println("f1 failed:", e)
} else {
fmt.Println("f1 worked:", r)
}
}
for _, i := range []int{7, 42} {
if r, e := f2(i); e != nil {
fmt.Println("f2 failed:", e)
} else {
fmt.Println("f2 worked:", r)
}
}
|
커스텀 에러에서 프로그래밍적으로 데이터를 사용하려면, 타입 단언(type assertion)을 통해 커스텀 에러의 인스턴스로 에러값을 받아와야 합니다. |
_, e := f2(42)
if ae, ok := e.(*argError); ok {
fmt.Println(ae.arg)
fmt.Println(ae.prob)
}
}
|
$ go run errors.go
f1 worked: 10
f1 failed: can't work with 42
f2 worked: 10
f2 failed: 42 - can't work with it
42
can't work with it
|
|
에러 핸들링에 대해 더 알고 싶다면 Go 블로그의 great post를 보세요. |
다음 예제: 고루틴.