У двух указателей на структуры одинаковое содержимое. Что проверит оператор == и при каком условии он вернёт true?
Оператор == сравнивает сами значения указателей, то есть идентичность объектов, на которые они указывают, а не содержимое структур. Для обычных структур результат будет true, если оба указателя указывают на одну переменную либо оба равны nil.
Указатели в Go нужны не только для доступа к данным, но и для явного выражения совместного владения одним объектом. Поэтому сравнение указателей сохраняет смысл сравнения идентичности, тогда как сравнение содержимого выполняется отдельно — после разыменования.
Такой подход позволяет отличать два независимо созданных объекта с одинаковыми полями от двух ссылок на один объект. Это важно для структур состояния, узлов графов, кэшей и других объектов, где существенна именно принадлежность к одному экземпляру.
Две структуры могут иметь полностью одинаковые поля, но находиться в разных областях памяти и изменяться независимо. Если ошибочно трактовать == указателей как сравнение содержимого, можно принять разные объекты за один и нарушить логику дедупликации, кэширования или проверки владения.
Обратная ошибка тоже опасна: иногда нужно проверить, что две переменные ссылаются на один объект, а сравнение разыменованных структур проверяет только равенство их текущих значений. Кроме того, структуры должны быть сравнимыми, если их сравнивают после разыменования.
Для указателей одного совместимого типа выражение p == q не читает поля структуры. Оно сравнивает указательные значения. Поэтому два указателя, созданные для двух разных структур с одинаковыми полями, обычно не равны, а указатель и его копия равны.
Выражение *a == *b уже сравнивает структуры по полям. Оно допустимо только если все поля структуры сравнимы: например, числа, строки, указатели и массивы сравнимых типов допустимы, а срезы, map и функции — нет.
Нулевые указатели сравниваются безопасно: p == nil проверяет отсутствие объекта и не разыменовывает p. Разыменование нулевого указателя, напротив, приводит к панике.
Есть специальная оговорка для указателей на переменные нулевого размера: указатели на разные такие переменные могут оказаться равными или неравными. На проверку идентичности обычных структур с данными это практически не влияет, но полагаться на уникальность адреса объекта нулевого размера нельзя.
В кэше хранятся объекты конфигурации. Два вызова построили конфигурации с одинаковым портом, но один из них должен считаться тем же объектом только после передачи общей ссылки.
Можно сравнивать *a == *b: это выявляет одинаковое содержимое, но требует сравнимости всех полей и не отличает независимые экземпляры. Можно присваивать и сравнивать указатели: это проверяет именно общность объекта, однако не отвечает на вопрос, равны ли текущие настройки.
Выбранное решение зависит от требования. Для проверки идентичности используют a == b, а для проверки содержимого — явное сравнение значимых полей или отдельный метод сравнения. Такое разделение предотвращает смешение понятий «тот же объект» и «одинаковое состояние».
== у указателей содержимое структур?Нет. Он сравнивает указательные значения и не выполняет неявное разыменование. Чтобы сравнить содержимое, нужно явно сравнить значения после разыменования, причём структура должна быть сравнимой.
Для обычных переменных указатели на разные объекты не равны. Исключение — переменные нулевого размера: спецификация допускает, что указатели на разные такие переменные могут иметь одинаковое значение. Поэтому адрес нельзя использовать как универсальный источник уникального идентификатора без дополнительных гарантий.
nil безопасно, а обращение к его полям — нет?Проверка p == nil работает только со значением указателя и не обращается к объекту. Выражение вроде p.Field требует разыменовать указатель; если он равен nil, объект отсутствует, и выполнение завершается паникой.