Сколько весит указатель в Go
Что проверяют
Понимаете ли вы разницу между размером указателя и размером того, на что он указывает, и знаете ли, какие ещё типы в Go внутри устроены поверх указателя. Это разминка перед разговором про копирование структур, escape analysis и нагрузку на сборщик мусора.
Как отвечать
Указатель занимает машинное слово: 8 байт на 64-битной платформе и 4 байта на 32-битной. Проверяется через unsafe.Sizeof, это константа времени компиляции, и считает она только само значение, а не то, что лежит по адресу.
Дальше главное, ради чего вопрос и задают: типов указательного размера в Go несколько.
var s []int
var str string
var i any
unsafe.Sizeof(s) // 24: указатель, длина, ёмкость
unsafe.Sizeof(str) // 16: указатель и длина
unsafe.Sizeof(i) // 16: тип и данныеmap, chan и функция занимают одно слово, внутри каждого указатель на служебную структуру. Практический вывод: передача слайса «по значению» копирует 24 байта заголовка, а не элементы, и от изменения содержимого это не защищает.
Стоит добавить, что указатель не всегда дешевле копии. Значение, на которое взяли указатель, часто уезжает в кучу, и вместо экономии получается лишняя работа сборщику. Небольшую структуру выгоднее копировать, а решает это компилятор, и посмотреть решение можно флагом -gcflags=-m.
Где спотыкаются
Отвечают «зависит от архитектуры» и замолкают. Ответ верный, но пустой: собеседника интересует, что из этого следует для структур, слайсов и интерфейсов.
Второе: считают, что unsafe.Sizeof показывает полный объём данных. Для структуры с указателями она вернёт размер полей, а не то, что за ними, а для слайса всегда 24 байта, независимо от длины.
Третье: забывают про выравнивание. Поля структуры дополняются до кратности своему размеру, поэтому перестановка полей меняет итоговый размер, и bool между двумя восьмибайтовыми полями стоит не один байт, а восемь.