Как создать многоуровневые подтипы ошибок в Go - PullRequest
0 голосов
/ 13 июня 2019

Я пытался создать подтипы ошибок в GO. Я задавал вопрос ранее относительно этого вопроса.

Теперь у меня проблема с несколькими типами. Следующий код показывает определения типов ошибок:

/* Interfaces */
type UniversalError interface {
    CommonError1
}

type CommonError1 interface {
    error
    CommonError1()
}

/* Structs */
type Error1 struct {
    reason string
}

type Error2 struct {
    reason string
}

type Error3 struct {
    reason string
}

/* Interface function implementations */
func (error1 Error1) Error() string {
    return fmt.Sprintf(error1.reason)
}

func (error2 Error2) Error() string {
    return fmt.Sprintf(error2.reason)
}

func (error3 Error3) Error() string {
    return fmt.Sprintf(error3.reason)
}

func (Error1) CommonError1() {}
func (Error2) CommonError1() {}
func (Error3) UniversalError() {}

Когда я пытаюсь запустить следующий код:

func main() {
    var err1 = Error1{reason: "Error reason 1"}
    var err2 = Error2{reason: "Error reason 2"}
    var err3 = Error3{reason: "Error reason 3"}

    fmt.Println("\n**** Types *****")
    printType(err1)
    printType(err2)
    printType(err3)
}

func printType(param error) {
    switch param.(type) {
    case UniversalError:
        switch param.(type) {
        case CommonError1:
            switch param.(type) {
            case Error1:
                fmt.Println("Error1 found")
            case Error2:
                fmt.Println("Error2 found")
            default:
                fmt.Println("CommonError1 found, but Does not belong to Error1 or Error2")
            }
        default:
            fmt.Println("Error3 Found")
        }
    default:
        fmt.Println("Error belongs to an unidentified type")
    }
}

Функция printType() выводит следующее:

**** Types *****
Error1 found
Error2 found
CommonError1 found, but Does not belong to Error1 or Error2

Мне нужно, чтобы тип Error3 был идентифицирован как UniversalError, но не как CommonError1. Как мне этого добиться? Что-то не так в моем подходе?

1 Ответ

1 голос
/ 13 июня 2019

Вы используете метод UniversalError(), но вы не добавили его в определение интерфейса, поэтому сделайте это:

type UniversalError interface {
    CommonError1
    UniversalError()
}

И вы хотите, чтобы Error3 было UniversalError. Чтобы Error3 было UniversalError, оно должно реализовать все свои методы: UniversalError() и CommonError1(). Таким образом, вы должны добавить оба этих метода:

func (Error3) CommonError1()   {}
func (Error3) UniversalError() {}

С этими изменениями вывод будет (попробуйте на Go Playground ):

**** Types *****
Error belongs to an unidentified type
Error belongs to an unidentified type
CommonError1 found, but Does not belong to Error1 or Error2

Подсказка: Если вы хотите гарантировать во время компиляции, что какой-то конкретный тип реализует некоторый интерфейс, используйте пустое объявление переменной, например:

var _ UniversalError = Error3{}

Приведенное выше объявление присваивает значение Error3 переменной типа UniversalError. Если Error3 не удовлетворяет UniversalError, вы получите ошибку во время компиляции. Приведенное выше объявление не вводит новую переменную, так как использовался пустой идентификатор , это просто проверка во время компиляции.

Если вы удалите метод Error3.CommonError1():

//func (Error3) CommonError1()   {}
func (Error3) UniversalError() {}

Тогда вы сразу получите сообщение об ошибке компиляции:

./prog.go:49:5: cannot use Error3 literal (type Error3) as type UniversalError in assignment:
    Error3 does not implement UniversalError (missing CommonError1 method)
...