9 вопросов
Чтобы метод мог изменять получателя и избежать копирования большой структуры. Вызов возможен и для T, и для *T. При вызове для значения компилятор передаёт адрес. Единообразие: если один метод с *T, обычно все методы получателя делают с *T.
Нет. Нельзя прибавлять к указателю число, вычитать указатели (кроме unsafe). Безопасность и упрощение модели памяти. Для обхода слайса используют индекс; для низкоуровневого доступа - пакет unsafe (не рекомендуется без необходимости).
Функция может изменить значение по месту; передаётся только адрес (8 байт), не копируется значение. Общие данные между вызывающим и функцией. Для int редко нужно; чаще указатели для структур, когда нужно мутировать или структура большая.
По значению: маленькие структуры, неизменяемые данные, не хотим мутировать. По указателю: большие структуры (меньше копирования), нужно изменить получателя, структура содержит мьютекс/слайс/map (копирование мьютекса небезопасно). Методы с pointer receiver позволяют мутировать.
Слайсы, map, каналы - заголовки; при присваивании копируется заголовок, данные общие. Добавление в слайс, изменение map видно снаружи. Но заменить сам слайс/map (переназначить переменную) снаружи нельзя - только содержимое. Для структур и примитивов изменение внутри функции без указателя не видно снаружи.
Разыменование: *p даёт значение по адресу p. Чтение или запись: x = *p, *p = x. Для nil указателя *p вызывает панику. Оператор & даёт адрес переменной: p := &x.
Обращение по нулевому указателю: *p или вызов метода через p.M(), когда p == nil. Вызывает панику. Нужно проверять указатель перед использованием или гарантировать инициализацию. Частая причина - неинициализированная структура или ошибочное предположение о возвращаемом значении.
Компилятор выполняет escape analysis: если указатель на переменную "убегает" (возвращается, сохраняется в глобальную переменную, передаётся в канал и т.д.), переменная размещается в куче. Иначе - на стеке. Разработчик не задаёт явно; можно смотреть через go build -gcflags="-m".
unsafe.Sizeof(x) возвращает размер в байтах, занимаемый значением типа x (или переменной x). Размер типа без учёта косвенно указываемых данных (для слайса - заголовок, не длина массива). Выравнивание может добавлять padding в структурах. Пакет unsafe - для низкоуровневого кода.