Чтение, ok и delete
Хендлер GET /files/{id} отвечал одинаково на «файла нет» и «файл пуст»: в обоих случаях клиент получал пустоту. Аня поймала это на ревью, когда пустой файл клиента вернулся как «не найден».
чтение отсутствующего ключа возвращает zero value, поэтому отличие «ключа нет» от «значение — ноль» даёт второе возвращаемое значение ok; delete безопасен для отсутствующего ключа и на nil-карте.
Отсутствующий ключ
Что здесь показано
- Стек — локальные переменные функции.
i = 3— значение;p = ptr → 10— указатель на значение;b = "hello"— срез (заголовок: указатель + длина + ёмкость). - Куча — данные, на которые ссылаются переменные:
rodata— байты строки-литерала (в бинарнике),данные N Б— бэкинг-массив слайса,строка— динамическая строка. - Горутины — лёгкие потоки Go: статус (running/runnable/waiting…), функция, в которой каждая сейчас находится, размер стека (растёт по мере работы) и пометка «из main» — горутина запущена из твоего кода.
- GC — сборщик мусора: фаза (off/mark) и число завершённых циклов.
Чтение несуществующего ключа не ошибка: возвращается zero value типа значения. Для счётчиков это удобно: filesByID[k]++ работает, даже если ключа ещё не было.
Ok-идиома
Но zero value не различает «ключа нет» и «значение — ноль». Для этого у чтения есть вторая форма:
v, ok := filesByID["b"]
if !ok {
fmt.Println("файла нет")
}
ok == true означает, что ключ в карте есть, и v — его значение, даже если оно нулевое. Это единственный способ отличить.
Delete безопасен
Что здесь показано
- Стек — локальные переменные функции.
i = 3— значение;p = ptr → 10— указатель на значение;b = "hello"— срез (заголовок: указатель + длина + ёмкость). - Куча — данные, на которые ссылаются переменные:
rodata— байты строки-литерала (в бинарнике),данные N Б— бэкинг-массив слайса,строка— динамическая строка. - Горутины — лёгкие потоки Go: статус (running/runnable/waiting…), функция, в которой каждая сейчас находится, размер стека (растёт по мере работы) и пометка «из main» — горутина запущена из твоего кода.
- GC — сборщик мусора: фаза (off/mark) и число завершённых циклов.
delete не возвращает ошибок и не паникует на отсутствующем ключе. Вызвать его можно даже на nil-карте — ничего не произойдёт. Поэтому код очистки не нужно оборачивать в проверки.
Вы узнаете:
- как отличаются счётчики через
m[k]++и через явныйok - как работать с nil-значениями в карте
map[string]*FileMeta
Проверьте себя
m := map[string]int{}. Что выведет fmt.Println(m["x"]), а затем m["x"]++; fmt.Println(m["x"])?
delete(m, "missing") и delete на nil-карте — что произойдёт?
Как отличить «ключа нет» от «значение равно нулю»?
правильных ответов
Нет ключа → zero value; нужен факт наличия → v, ok := m[k]; delete безопасен для отсутствующего ключа и на nil-карте.
10 000 ₽ · 60 минут · онлайн