суббота, 26 января 2019 г.

Эффективный Go: карты (maps)

Карты - это удобная и мощная встроенная структура данных, которая связывает значения одного типа (ключ) со значениями другого типа (элемент или значение). Ключ может быть любого типа, для которого определен оператор равенства, таким как целое число, число с плавающей запятой и комплексное число, строка, указатель, интерфейс (пока динамический тип поддерживает равенство), структура и массив. Срезы не могут быть использованы в качестве ключей карты, потому что равенство не определено на них. Как и срезы, карты содержат ссылки на базовую структуру данных. Если вы передаете карту в функцию, которая изменяет содержимое карты, изменения будут видны и у вызвавшего.

Карты могут быть построены с использованием обычного составного литерального синтаксиса с разделенными двоеточиями парами ключ-значение, поэтому их легко построить во время инициализации.

var timeZone = map[string]int{
    "UTC":  0*60*60,
    "EST": -5*60*60,
    "CST": -6*60*60,
    "MST": -7*60*60,
    "PST": -8*60*60,
}

Назначение и выборка значений карты выглядит синтаксически так же, как выполнение того же самого для массивов и срезов, за исключением того, что индекс не должен быть целым числом.

offset := timeZone["EST"]

Попытка получить значение карты с ключом, который отсутствует в карте вернет нулевое значение для типа из записей в карте. Например, если карта содержит целые числа, поиск несуществующего ключа вернет 0. Сет (набор уникальных значений) может быть реализован как карта с типом значения bool. Задайте для элемента карты значение true, чтобы поместить значение в сет, а затем проверяйте его с помощью простой индексации.

attended := map[string]bool{
    "Ann": true,
    "Joe": true,
    ...
}

// условие будет false если персона не в карте
if attended[person] { 
    fmt.Println(person, " был на встрече")
}

Иногда вам нужно отличить отсутствующую запись от нулевого значения. Есть ли запись для "UTC" или это 0, потому что его нет в карте вообще? Вы можете различать с помощью формы множественного назначения.

var seconds int
var ok bool
seconds, ok = timeZone[tz]

По понятным причинам это называется “comma ok” идиома. В этом примере, если присутствует tz, seconds будет установлен соответствующим образом, и ok будет true; если нет, seconds будет установлен равным нулю, а ok быть false. Вот функция, которая объединяет это с хорошим сообщением об ошибке:

func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    }
    log.Println("unknown time zone:", tz)
    return 0
}

Чтобы проверить наличие в карте, не беспокоясь о фактическом значении, вы можете использовать пустой идентификатор(_) вместо обычной переменной для значения.

_, present := timeZone[tz]

Чтобы удалить запись в карте, используйте встроенную функцию delete, аргументами которой являются карта и ключ для удаления. Это безопасно делать, даже если ключ уже отсутствует в карте.

delete(timeZone, "PDT")


Читайте также:


Комментариев нет:

Отправить комментарий