Почему пользовательская переменная ошибки Голанга имеет несколько типов - PullRequest
0 голосов
/ 23 января 2019

Я новый суслик, и меня действительно смущают типы переменных, если я определяю пользовательскую ошибку

    import (
        "fmt"
        "reflect"
    )

    // custom errors
    type myError struct {
        msg string
    }

    func (m *myError) Error() string {
        return m.msg
    }

    func errorGen() error {
        return &myError{"custom error"}
    }

сгенерируйте новую ошибку и проверьте ее тип

    func main() {
        e := errorGen()
        fmt.Println(reflect.TypeOf(e).Kind()) // type = pointer

        // first type assertion
        _, ok := e.(error)
        if ok {
            fmt.Println("type assertion error") // type = error
        }

        // second type assertion
        _, ok = e.(*myError)
        if ok {
            fmt.Println("type assertion *myError") // type = pointer
        }
    }

, поэтому в приведенной выше кодовой переменной 'e' показаны 2 типа одновременно. Что именно типа е? и почему «ошибка» является интерфейсом и также может использоваться как тип возвращаемого значения?

Большое спасибо

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Необходимо различать «статический тип» и «динамический тип» переменной.

Каждая переменная в Go имеет ровно один статический тип.Пример:

  • После объявления a := 5 статический тип a равен int, и это все, что нужно знать о a.
  • Статический тип e в вашем коде - error (потому что это то, что errorGen возвращает).
  • Вы можете явно указать статический тип следующим образом: var b uint16 = 9.

Теперь в Go есть типы интерфейсов.error такой тип интерфейса, см. Ответ Питера.Некоторые переменные будут иметь error в качестве статического типа;ваш e является примером.Теперь, целое назначение переменной типа интерфейса - хранить значения различных типов, которые реализуют этот интерфейс.Таким образом, переменная интерфейса, которая не равна nil, каким-то образом «содержит» другую переменную (на самом деле значение).Тип этого содержимого может быть любым, который реализует интерфейс.Тип содержащегося значения - «динамический тип».Утверждение типа позволяет извлекать значения этого динамического типа.

0 голосов
/ 23 января 2019

Спецификация языка программирования Go

Ошибки

Ошибка предварительно объявленного типа определяется как

type error interface {
    Error() string
}

Это обычный интерфейс для представления состояния ошибки, при этом значение nil не представляет ошибки.

Типы интерфейса

Тип интерфейса определяет набор методов, называемый егоинтерфейс.Переменная типа интерфейса может хранить значение любого типа с набором методов, который является любым надмножеством интерфейса.Говорят, что такой тип реализует интерфейс.


e реализует предварительно объявленный тип интерфейса error.

    // first type assertion
    _, ok := e.(error)
    if ok {
        fmt.Println("type assertion error") // type = error
    }

e конкретный типявляется указателем на тип myError.

    // second type assertion
    _, ok = e.(*myError)
    if ok {
        fmt.Println("type assertion *myError") // type = pointer
    }

Оба утверждения типа верны (ok is true).

...