Go абстракций и ошибок - PullRequest
       18

Go абстракций и ошибок

2 голосов
/ 16 января 2020

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

Каков правильный способ обработки ошибок в таком случае?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...