Что происходит при передаче nil по указателю и обращении к полю в Go
Что проверяют
Отличаете ли вы nil указателя от nil интерфейса и знаете ли, что не всякий вызов на нулевом указателе падает. Вопрос выглядит как основы, а разворачивается в самую частую ошибку Go при возврате ошибок.
Как отвечать
Коротко: чтение или запись поля через нулевой указатель это разыменование нулевого адреса. Рантайм ловит его и вызывает панику invalid memory address or nil pointer dereference. Паника раскручивает стек и валит программу, если её не перехватил recover в отложенной функции.
Дальше стоит показать границы правила:
- метод с приёмником-указателем можно вызвать на
nil, и он отработает, пока не обращается к полям. На этом строят, например, безопасные методы обхода дерева; - метод с приёмником-значением на
nilпадает сразу: чтобы скопировать значение, его надо разыменовать; - чтение из нулевой мапы и
lenпо нулевому слайсу работают,appendк нулевому слайсу тоже, а вот запись в нулевую мапу паникует; - вложенные указатели требуют проверки каждого звена, проверка верхнего уровня не гарантирует ничего.
type Person struct{ Name string }
var p *Person
fmt.Println(p == nil) // true
fmt.Println(p.Name) // panicПрактический вывод: указатель, который может быть нулевым, проверяют на границе, а не в каждой функции ниже по стеку, и договариваются в сигнатуре, кто за эту проверку отвечает.
Где спотыкаются
Кладут нулевой указатель конкретного типа в интерфейс error и сравнивают с nil. Интерфейс хранит тип и значение, поэтому он не равен nil, даже когда значение нулевое, и вызывающий код уходит в ветку ошибки. Лечится возвратом буквального nil, а не переменной типа *MyError.
Второе: ловят панику через recover и считают вопрос закрытым. Перехватить её можно, но состояние программы после этого неизвестно, поэтому такой перехват уместен как последний рубеж на уровне запроса, а не как замена проверке.
Третье: путают нулевой указатель и нулевое значение структуры. var p *Person это отсутствие объекта, var p Person это готовая структура с пустыми полями, и обращение к её полю совершенно законно.