Значение само по себе не описывает наличие
Представим отображение количества материалов в вымышленной мастерской. Для бумаги записано три, для ткани ноль, а ключа для пуговиц нет. Обычное чтение количества ткани и пуговиц в отображении целых чисел вернёт одинаковое числовое значение. Однако смысл разный: нулевое количество ткани задано, а сведения о пуговицах отсутствуют. Проверка только на равенство нулю объединит эти состояния. Если задача требует отличать известный нулевой остаток от отсутствия сведений, такое объединение становится логической ошибкой, хотя само чтение выполняется корректно.
Два результата сохраняют различие
В Go обращение к элементу map допускает получение двух результатов: значения и логического признака наличия ключа. Для существующего ключа признак равен true, для отсутствующего false. Часто его называют ok, но смысл задаётся операцией, а не выбранным именем переменной. В нашей модели ткань даст ноль вместе с true, пуговицы ноль вместе с false. Для бумаги получится три вместе с true. Такое представление позволяет отдельно решить, что делать с отсутствием: показать неизвестное состояние, запросить данные или применить явно оговорённое значение по умолчанию.
Пустота отображения и готовность к записи различаются
Нулевое значение самой переменной типа map называется nil. Из такого отображения можно читать: результатом будет нулевое значение типа элемента и отсутствие ключа. Но записывать элемент в nil map нельзя: такая операция вызывает панику времени выполнения. Для записи требуется инициализированное отображение, например созданное через make или литерал. При этом пустое инициализированное отображение и nil map оба могут иметь длину ноль. Поэтому длина не заменяет понимания состояния структуры. Это отдельный вопрос от проверки наличия конкретного ключа, и смешивать две проверки не следует.
Попробуйте на практике
Смоделируйте чтение map с целочисленными значениями на бумаге. Запускать код и устанавливать программное обеспечение не нужно.
- Создайте две карточки записей: бумага со значением три и ткань со значением ноль. Укажите, что ключ пуговицы не добавлен. Считайте эту модель инициализированным отображением, готовым к записи.
- Для каждого из трёх ключей запишите результат обычного чтения. Получатся три, ноль и ноль. Рядом отметьте, почему последние два числа ещё не доказывают одинакового состояния данных.
- Добавьте признак наличия: для бумаги true, для ткани true, для пуговиц false. Сформулируйте сообщение для отсутствующих данных, которое не утверждает, что известен нулевой остаток.
- Нарисуйте отдельно nil map и пустое инициализированное отображение. У обоих подпишите длину ноль. Отметьте, что чтение отсутствующего ключа допустимо в обоих случаях, а запись элемента требует инициализированного отображения.
Как проверить результат. Ноль для существующего ключа отделён от нуля при отсутствии. Логические признаки соответствуют карточкам. Пустое отображение не перепутано с nil map, а допустимость чтения не выдана за допустимость записи.
Частые вопросы
Всегда ли нужно получать признак наличия?
Нет. Иногда значение по умолчанию как раз соответствует задаче, например при подсчёте накопленного количества. Но это должно быть осознанным решением о смысле отсутствия, а не случайным следствием проверки числа.
Если тип значения не целочисленный, отсутствие тоже даст ноль?
Возвращается нулевое значение соответствующего типа: например, пустая строка для string или false для bool. Оно также может быть сохранено явно, поэтому вопрос о наличии ключа остаётся отдельным.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.