假设我需要对具有方法的某种类型进行抽象,该方法Do
返回一个error
package main
import "myproject/complex"
type Doer interface {
Do(i int) error
}
func main() {
var doer Doer
doer = complex.Doer{}
i := 1 // or any integer
err = doer.Do(i)
// How to check which error was returned?
}
package complex
type Doer struct{}
func (Doer) Do(i int) error {
if i < 0 {
return fmt.Errorf("negative numbers not allowed") // or any complex nested error but this can be expected (bad input, etc)
}
if i == 40 {
return fmt.Errorf("this number cannot be used") // or any complex nested error but this can be expected (bad input, etc)
}
if i > 100 {
return fmt.Errorf("some unknown error, everything broke") // or any complex nested error which is unexpected (e. g. some 3rd party failure)
}
}
我需要一个更好的架构来识别这是否是已知错误。我可以做到 java 风格,让实现知道我们的错误类型。例如
package do
type Doer interface {
Do(i int) error
}
var (
ErrNegative = fmt.Errorf("negative numbers not allowed")
ErrCannotBeUsed = fmt.Errorf("this number cannot be used")
)
package complex
import (
"myproject/do"
)
type Doer struct{}
func (Doer) Do(i int) error {
if i < 0 {
return do.ErrNegative
}
if i == 40 {
return do.ErrCannotBeUsed
}
if i > 100 {
return fmt.Errorf("some unknown error, everything broke")
}
}
package main
import (
"errors"
"myproject/complex"
"myproject/do"
)
func main() {
var doer do.Doer
doer = complex.Doer{}
i := 1 // or any integer
err = doer.Do(i)
if err == nil {
return
}
if errors.Is(err, do.ErrNegative) {
// some handling
} else if errors.Is(err, do.ErrCannotBeUsed) {
// some handling
} else {
// handle unknown error
}
}
然而,在这样的架构中,我会强制实现 ( complex.Doer
) 适应接口 ( do.Doer
),根据Go Wiki,这不是接口应该被使用的方式。
在这种情况下处理错误的正确方法是什么?