Указатели
Указатель в Go — это значение, которое хранит адрес другой переменной в памяти. Оператор & берёт адрес (&x имеет тип *T), а оператор * разыменовывает указатель (*p — это значение, на которое он смотрит). Скобок и стрелок (->) нет: к полям структуры через указатель обращаются обычным p.Field, Go разыменовывает сам.
За этой простотой прячется главное, что проверяют на junior-секции: Go передаёт всё по значению — аргументы и присваивания копируются, поэтому функция не может изменить переменную вызывающего, пока не получит *T и не запишет через него. Нулевое значение указателя — nil, и разыменование nil роняет программу паникой invalid memory address. Арифметики указателей в Go нет вовсе — нельзя сдвинуть указатель на следующий элемент, как в C. Тема разбирает указатели по слоям — от операторов до нулевого указателя.
Карта темы
- Основы указателей —
&xберёт адрес и даёт*T,*pразыменовывает; указатель хранит адрес в памяти; нулевое значение —nil; в Go нет арифметики указателей. - По значению против ссылки — Go передаёт всё по значению (копии); чтобы изменить переменную вызывающего, передают
*Tи пишут через него; слайсы/map/каналы ведут себя как ссылки — копируется заголовок, но он делит общий буфер. - Нулевой указатель —
nil— это нулевой указатель; разыменованиеnilроняет паникуinvalid memory address; проверяйте перед разыменованием; метод наnil-приёмнике легален, пока не разыменует его.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
| Ждать, что функция изменит переданную переменную | Go копирует аргумент; без *T функция меняет копию, оригинал нетронут |
| Передавать большую структуру по значению ради «изменения» | Создаётся копия — изменения теряются, а копирование ещё и тратит память |
Сдвигать указатель арифметикой, как в C (p + 1) | Не компилируется — в Go нет арифметики указателей |
Разыменовывать указатель без проверки на nil | Паника invalid memory address в рантайме, а не ошибка сборки |
Считать, что копия слайса/map независима от оригинала | Заголовок копируется, но буфер общий — изменение элементов видно обеим переменным |
Писать (*p).Field вместо p.Field | Лишне: Go разыменовывает указатель на структуру автоматически |
Значение для собеседований
Указатели — junior-фильтр на «понимает модель памяти Go» против «переносит привычки из C или прячется от указателей вовсе». Сам синтаксис тривиален, но следствия из «всё по значению» и из nil спрашивают почти всегда.
Что обычно проверяют:
- Что делают
&и*и почему у Go нет арифметики указателей и оператора->. - Почему функция не меняет переменную вызывающего без
*T(передача по значению). - Почему слайсы,
mapи каналы выглядят «ссылочными», хотя сам Go всё копирует. - Что такое
nil-указатель и почему его разыменование роняет программу. - Когда указатель действительно нужен (изменение через границу функции, большие структуры), а когда копия дешевле и безопаснее.