Почему при передаче указателя на структуру в функцию изменяется значение, а при передаче значения — нет
Что проверяют
Понимаете ли вы, что в Go всё передаётся по значению, включая сам указатель, и умеете ли осознанно выбирать приёмник метода. Вопрос базовый, но по нему видно, думает кандидат про память или заучил правило.
Как отвечать
Передачи по ссылке в Go нет: аргумент копируется всегда. Разница в том, что именно копируется. При func f(p Person) копируется вся структура, и запись в поле меняет копию, которая умирает на выходе. При func f(p *Person) копируется адрес, обе копии смотрят на одну и ту же память, и запись через p.Name (сокращение от (*p).Name) меняет оригинал.
type Person struct{ Name string }
func byValue(p Person) { p.Name = "new" }
func byPointer(p *Person) { p.Name = "new" }
person := Person{Name: "old"}
byValue(person) // Name остался old
byPointer(&person) // Name стал newТо же самое с приёмниками методов: func (p *Person) Rename() меняет объект, func (p Person) Rename() меняет копию. Компилятор сам берёт адрес у адресуемой переменной, поэтому person.Rename() работает, но у значения из мапы адреса нет и такой вызов не соберётся.
Стоит добавить про слайсы, мапы и каналы: они тоже передаются по значению, но внутри лежит дескриптор со ссылкой на данные. Поэтому s[0] = 1 внутри функции видно снаружи, а append может переехать в новый массив, и тогда не видно ничего.
Где спотыкаются
Говорят, что указатель всегда быстрее. Для маленькой структуры копия дешевле разыменования, а взятие адреса нередко уводит значение в кучу по результатам escape analysis и добавляет работы сборщику.
Смешивают приёмники в одном типе: часть методов на значении, часть на указателе. Тогда метод-сеттер на значении молча правит копию, а интерфейс оказывается реализован только для *T, и передача T перестаёт компилироваться.
Думают, что через указатель можно поменять саму переменную вызывающего. Присваивание p = &other внутри функции переставляет только локальную копию указателя. Чтобы переставить исходный указатель, нужен **Person или возврат значения.