В языке Go значение nil
используется для обозначения отсутствия данных.
Оно является нулевым значением для типов, которые работают с указателями (указатели, срезы, карты, каналы, функции, интерфейсы). Рассмотрим примеры тех типов, которые мы уже изучили
nil для указателей
var ptr *int
fmt.Println(ptr == nil) // => true
Переменная указательного типа содержит nil
, если не была явно инициализирована. Это означает, что она не указывает ни на какую область памяти.
Попытка разыменовать nil
-указатель приводит к панике во время выполнения:
var ptr *int
fmt.Println(*ptr) // panic: invalid memory address or nil pointer dereference
Чтобы избежать ошибки, перед разыменованием указателя выполняется проверка:
if ptr != nil {
fmt.Println(*ptr)
}
nil
в полях структур
Если структура содержит указательное поле, это поле по умолчанию будет nil
, если его не инициализировать.
type User struct {
Name *string
}
func main() {
var u User
fmt.Println(u.Name == nil) // => true
}
Такую структуру можно проверить перед использованием указателя в поле:
if u.Name != nil {
fmt.Println(*u.Name)
}
Вызов методов на nil
Если метод вызывается на значении, равном nil
, и этот метод не обращается к полям внутри объекта, то ошибка не возникает:
type Logger struct{}
func (l *Logger) Info() {
fmt.Println("Log info") // => Log info
}
func main() {
var l *Logger
l.Info() // работает, несмотря на то что l == nil
}
Такое поведение разрешено в Go по дизайну. Аргумент l
— это просто указатель на Logger
, и метод может быть вызван даже на nil
, если внутри метода нет обращения к данным. Это позволяет, например, реализовать "пустые" или "заглушки" (no-op
реализации), где метод ничего не делает, но при этом вызывается безопасно.
Но если метод попытается обратиться к данным внутри структуры, произойдёт паника:
type User struct {
Name string
}
func (u *User) PrintName() {
fmt.Println(u.Name)
}
func main() {
var u *User
u.PrintName() // panic: invalid memory address or nil pointer dereference
}
Вывод
nil
— это значение по умолчанию для ссылочных типов, таких как указатели. Оно часто используется в Go и требует проверки перед обращением к данным.