Это правда, что значения интерфейса сопоставимы, но вы можете сравнивать только те значения, которые назначаются друг другу (точнее, одно назначается другому). Цитирование из Spec: Операторы сравнения:
В любом сравнении, первый операнд должен быть присваиваемым типу второго операнда или наоборот.
Вы не можете присвоить значение error
для io.Reader
, и вы не можете присвоить значение io.Reader
для error
, поэтому вы не можете их сравнить.
Они могут хранить или не хранить одно и то же динамическое значение. Если вы хотите сравнить их, сначала закройте оба к interface{}
, чтобы вы могли сравнить их, например ::
fmt.Println(interface{}(err) == interface{}(reader))
Будет выведено (попробуйте на Go Playground ):
true
Примечание: на самом деле было бы достаточно преобразовать только одно из них в interface{}
, потому что таким образом другое значение станет сопоставимым с типом того значения, которое вы преобразовали в interface{}
(любое значение может быть преобразовано в interface{}
), так что было бы достаточно сделать:
fmt.Println(interface{}(err) == reader)
Проверка сравнения с не nil
значениями интерфейса:
type x int
func (x) Error() string { return "" }
func (x) Read([]byte) (int, error) { return 0, nil }
err = x(0)
reader = x(0)
fmt.Println(interface{}(err) == interface{}(reader))
reader = x(1)
fmt.Println(interface{}(err) == interface{}(reader))
Теперь вывод будет (попробуйте на Go Playground ):
true
false
Также не забывайте, что значение интерфейса nil
не равно значению интерфейса не nil
, содержащему динамическое значение nil
. Подробнее см. Сокрытие значений nil, понимание причины сбоя golang
Edit:
Пакет fmt
печатает значение внутри интерфейса, а не значение интерфейса. Цитирование из пакета документов fmt
:
Независимо от глагола, если операнд является значением интерфейса, используется внутреннее конкретное значение, а не сам интерфейс.
То же самое относится к reflect.TypeOf()
: он возвращает динамический тип, но если вы передаете ему значение интерфейса nil
, он возвращает nil
, поэтому пакет fmt
будет печатать nil
. Цитирую свой документ:
TypeOf возвращает тип отражения, который представляет динамический тип i. Если i - нулевое значение интерфейса, TypeOf возвращает ноль.