Допустим, мне нужна абстракция для некоторого типа, который имеет метод 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 , это не то, как должны использоваться интерфейсы.
Каков правильный способ обработки ошибок в таком случае?