Почему отражение имени (или пути к пакету) типа ошибки вызывает пани c в Go? - PullRequest
0 голосов
/ 15 апреля 2020

Использование отражения для получения имени или пути пакета типа error в Golang приводит к тому, что программа вызывает pani c (с panic: runtime error: invalid memory address or nil pointer dereference).

Что является причиной такого поведения ? (Выполнение той же операции для других встроенных типов возвращает имя типа и пустую строку для пути к пакету.)

Мне интересны условия дизайна языка - я не могу понять, почему для error типов желательно вести себя иначе, чем для других встроенных типов.

Например:

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var str string
    strType := reflect.TypeOf(str)
    fmt.Println(strType.Name()) // OK
    fmt.Println(strType.PkgPath())  // OK

    var err error
    errType := reflect.TypeOf(err)
    fmt.Println(errType.Name()) // panics
    fmt.Println(errType.PkgPath())  // also panics
}

Go детская площадка здесь: https://play.golang.org/p/JBMhMkjGPEV

1 Ответ

2 голосов
/ 15 апреля 2020

error не является особенным, за исключением того, что это интерфейс.

reflect.TypeOf принимает один аргумент типа interface{}. Если вы вызываете его с неинтерфейсным значением, значение и его тип будут заключены в interface{}. Если вы вызываете его со значением интерфейса, базовое значение и тип извлекаются из интерфейса и переносятся в новое значение interface{}. Если вы вызываете его с пустым интерфейсом (как вы делаете здесь, так как error является интерфейсом и инициализируется нулем), тогда нет базового значения и типа, а аргумент reflect.TypeOf является новым nil interface{} значение. reflect.TypeOf определено так, чтобы возвращать nil в этом случае, что приводит к вашим нулевым проблемам.

Я думаю, что вы путаетесь в том, что TypeOf значения интерфейса - это тип его базового значения, которое никогда не интерфейс. Вы бы хотели, чтобы TypeOf значения интерфейса было самим типом интерфейса, но это не так.

...