Проверка карт на nil
Часть раздела Логика и управление потоком путешествия по GO на Coddy. Урок 28 из 68.
В Go у map может быть специальное состояние, называемое nil. nil map — это по сути неинициализированный map, который ни на что не указывает в памяти. Понимание этой концепции крайне важно, поскольку попытка добавить ключи в nil map приведёт к panic и аварийному завершению программы.
Вот как возникает карта nil и как она выглядит:
var myMap map[string]int
// myMap равен nil на этом этапеКогда вы объявляете переменную map без инициализации, Go автоматически устанавливает для неё значение nil. Хотя из nil-map можно безопасно читать (она вернёт нулевое значение), попытка записать в неё вызовет панику:
// Это безопасно — возвращает 0
value := myMap["key"]
// Это вызовет панику!
myMap["key"] = 42Чтобы избежать этой проблемы, всегда выполняй check, является ли map nil, прежде чем пытаться add в него ключи. check прост:
if myMap == nil {
myMap = make(map[string]int)
}
myMap["key"] = 42 // Теперь это безопасноЭта простая check гарантирует, что ваша программа не завершится с ошибкой при работе с потенциально неинициализированными maps, делая ваш код более устойчивым и надежным.
Задание
ЛегкоСоздайте безопасную систему инициализации map, которая предотвращает ошибки panic, проверяя nil map перед попыткой выполнения операций записи. Эта задача демонстрирует критическую важность проверки состояния map перед выполнением операций, которые могут привести к сбою программы.
Вы получите два входных значения:
- Строку, представляющую количество операций (например,
"5") - Строку, содержащую операции, разделённые запятыми. Каждая операция указывает map, с которым она работает:
"check:[map_name]""init:[map_name]""add:[map_name]:[key]:[value]"
"check:scores,init:scores,add:scores:Alice:95,add:scores:Bob:87,check:grades"
Ваша задача:
- Создать две переменные map типа
map[string]intс именамиscoresиgradesбез инициализации (они будут nil) - Обрабатывать каждую операцию из входной строки sequentially:
- Для операций
"check":- Проверить, является ли указанный map nil
- Вывести
"Map [map_name] is nil", если map равен nil - Вывести
"Map [map_name] is initialized", если map не равен nil
- Для операций
"init":- Инициализировать указанный map с помощью
make(map[string]int) - Вывести
"Initialized map [map_name]"
- Инициализировать указанный map с помощью
- Для операций
"add":- Сначала проверить, является ли map nil
- Если map равен nil, вывести
"Cannot add to nil map [map_name]" - Если map не равен nil, добавить пару ключ-значение и вывести
"Added [key]:[value] to [map_name]"
- Разобрать операции, разделив входную строку:
- Разделить по запятым, чтобы получить отдельные операции
- Для каждой операции разделить по двоеточиям, чтобы получить тип операции и параметры
- Преобразовать строку со значением в целое число для операций add
- После обработки всех операций отобразить Final состояние обоих map:
- Для каждого map, если он равен nil:
"Final state - [map_name]: nil" - Для каждого map, если он инициализирован:
"Final state - [map_name]: [count] entries", где count — количество пар ключ-значение - Вывести
scoresпервым, аgradesвторым, независимо от порядка, в котором они использовались в операциях
- Для каждого map, если он равен nil:
Используйте пакет strconv, чтобы преобразовывать строки со значениями в целые числа для операций add. Эта задача демонстрирует, как проверка nil map перед операциями записи предотвращает runtime-панику и делает код надёжным и устойчивым.
Попробуйте сами
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Прочитать ввод
var numOpsStr string
var operationsStr string
fmt.Scanln(&numOpsStr)
fmt.Scanln(&operationsStr)
// Объявить maps без инициализации (они будут nil)
var scores map[string]int
var grades map[string]int
// Разделить operations по запятой
operations := strings.Split(operationsStr, ",")
// TODO: Напишите ваш код ниже
// Обработать каждую операцию последовательно
// Обработать операции "check", "init" и "add"
// Для операций add используйте strconv.Atoi() для преобразования строки value в integer
// Вывести конечное состояние обеих maps
// Проверить, являются ли maps nil или инициализированными, и вывести соответственно
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Продвинутое управление потоком выполнения
Switch с использованием `fallthrough`Выход из вложенных цикловПродолжение конкретного циклаОператор `goto`Итоги: Продвинутое управление циклами4Проект: Простой список задач
Настройка проектаДобавление задачи2Структуры и методы
Определение методов для структурПолучатели по значениюПолучатели по указателюВыбор типа получателяМетоды против функцийИтоги: поведение структур5Карты: подробный разбор
Карты структурУказатели как значения картПроверка карт на nilСравнение картИтоги: счетчик частоты слов3Интерфейсы (Основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование интерфейсных типовПустой интерфейсУтверждение типаПереключатель типовИтоги: Фигуры и поведениеПотренируйтесь самостоятельно: Онлайн-компилятор Go