Ответ
Интерфейс в Go внутренне представляет собой пару (type, value)
— конкретный тип и значение этого типа.
Nil-интерфейс — это интерфейс, у которого и тип, и значение равны nil
. То есть, пара выглядит как (nil, nil)
.
var i interface{} // Тип = nil, Значение = nil
fmt.Println(i == nil) // Выведет: true
Особенность и частая ошибка заключается в интерфейсе, который содержит nil
-указатель на конкретный тип. Такой интерфейс не является nil-интерфейсом, потому что его компонент type
не равен nil
.
var p *int // p - это nil-указатель на int
var i interface{} = p // Тип = *int, Значение = nil
// Проверка i == nil вернет false, так как тип в интерфейсе установлен (*int)
fmt.Println(i == nil) // Выведет: false
Это критически важно при обработке ошибок. Если функция возвращает ошибку типа *CustomError
, а вы возвращаете nil
этого типа, то результирующий интерфейс error
не будет равен nil
.
Правильный способ проверки:
Для безопасной проверки нужно использовать рефлексию или приведение типов.
if i != nil && !reflect.ValueOf(i).IsNil() {
// Интерфейс не nil и содержит не nil значение
}