Обмен технологиями

[Go series] массив, срез и карта

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Соедините предыдущую и следующую

Мы представили if и for в нашей предыдущей статье. Это не следует практиковать. Давайте попрактикуемся в их использовании.continue Оператор для вычисления суммы четных чисел в пределах 100. Когда мы пишем код,continueОператор поможет нам пропустить определенные итерации, которые не нужны, например, в этом примере мы пропустим все нечетные числа.

  1. sum := 0
  2. for i := 1; i < 100; i++{
  3. if i & 1 == 0 {
  4. continue
  5. }
  6. sum += i
  7. }
  8. fmt.Println("the sum is",sum)

Начать обучение

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

множество

Во-первых, давайте начнем с массивов. Массив — это самая базовая структура данных в Go. Это последовательность элементов одного типа фиксированной длины. После объявления массива его длину нельзя изменить. Объявление и инициализация массивов очень просты.

Объявить массив

При объявлении массива необходимо указать тип и длину массива. Вот как объявляется массив:

var arrayName [arrayLength]elementType

Например, объявите целочисленный массив длиной 5:

var numbers [5]int
инициализировать массив

Инициализировать массив можно различными способами:

  • Используйте буквальную инициализацию:
var numbers = [5]int{1, 2, 3, 4, 5}
  • использовать:=Краткое заявление:
numbers := [5]int{1, 2, 3, 4, 5}
  • Автоматически определить длину массива:
numbers := [...]int{1, 2, 3, 4, 5}
  • Укажите инициализацию индекса:
numbers := [5]int{0: 1, 4: 5}

Характеристики массивов

  • Фиксированная длина: длина массива определяется при его объявлении и не может быть изменена позже.
  • элементы одного типа: Массивы могут содержать элементы только одного типа.
  • распределение памяти последовательно: элементы массива располагаются в памяти последовательно, что делает доступ к элементам массива очень эффективным.

Доступ к элементам массива

Вы можете получить доступ к элементам массива по индексу, начиная с 0:

value := numbers[2] // 获取索引为 2 的元素

Траверсный массив

вы можете использоватьforПеребрать все элементы массива:

  1. for i, value := range numbers {
  2. fmt.Printf("Index: %d, Value: %dn", i, value)
  3. }

длина массива

Вы можете использовать встроенныйlenФункция для получения длины массива:

length := len(numbers)

нулевое значение массива

Если массив не инициализирован явно, его элементам автоматически присваивается нулевое значение их типа. Например, нулевое значение целочисленного массива равно 0:

var numbers [5]int // 所有元素都是 0

Многомерные массивы

Язык Go также поддерживает многомерные массивы. Ниже приведен пример объявления и инициализации целочисленного массива 2x3:

  1. var matrix [2][3]int
  2. matrix = [2][3]int{{1, 2, 3}, {4, 5, 6}}

Ограничения массивов

Поскольку длина массива фиксирована, в некоторых случаях это может быть не очень гибко. Если вам нужна коллекция переменной длины, вы можете использовать срезы.

кусочек

Далее идет срез — более гибкий встроенный тип, который можно рассматривать как динамический массив. Длина среза является переменной, и он создается на основе массива, что обеспечивает больше удобства. Вот как объявить и инициализировать срез:

  1. s := make([]int, 3) // 创建一个长度为3的整型切片
  2. s[0] = 1 // 切片元素赋值
  3. s[1] = 2
  4. s[2] = 3
  5. s = append(s, 4) // 向切片追加元素

В языке Go, хотя массивы и срезы используются для хранения серии элементов одного и того же типа, они имеют существенные различия в распределении памяти, изменчивости размера и использовании. Вот основные различия между массивами и срезами:

изменчивость размеров

  • множество : Размер массива определяется при его объявлении и не может быть изменен позже.Размер массива является частью его типа, поэтому[3]intи[4]intэто разные типы.
  • кусочек : Срезы являются динамическими и могут увеличиваться или уменьшаться во время выполнения.Размер среза не является частью его типа, поэтому[]intОбщий тип для всех целочисленных срезов.

выделение памяти

  • множество : Массивы — это типы значений, и когда массив передается в качестве параметра функции, передается копия его значения. Это означает, что изменения массива внутри функции не влияют на исходный массив.
  • кусочек : Slice — это ссылочный тип, который содержит указатель на базовый массив, длину и емкость среза. Когда срез передается в качестве параметра функции, передается копия указателя, поэтому изменения среза внутри функции повлияют на исходный срез.

инициализация

  • множество: При инициализации массива необходимо указать его размер, а значения элементам можно присвоить сразу.
  • кусочек: Срезы можно передавать через литералы,makeФункция или фрагмент массива для инициализации, размер не указан.

Образец кода

Вот примеры инициализации массивов и срезов:

  1. // 数组
  2. var arr [3]int = [3]int{1, 2, 3}
  3. // 切片
  4. var slice []int = []int{1, 2, 3}
  5. // 或者使用 make 函数
  6. slice := make([]int, 3)

Функциональные различия

  • множество: поскольку размер фиксирован, размер массива известен во время компиляции, что позволяет выделить память для массива в стеке, а временная сложность доступа к элементам массива равна O(1).
  • кусочек: Нарезка обеспечивает большую гибкость за счетappend Функция добавляет элементы или получает подсрезы посредством операций нарезки.Базовый массив среза может быть размещен в куче, и временная сложность доступа к элементам среза также равна O(1), ноappendМожет привести к перераспределению базового массива, что обычно является операцией O(n).

картографирование

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

Объявление и инициализация

объявить карту

Синтаксис объявления карты следующий:

var mapName map[keyType]valueType

Например, объявите карту с ключами как строками и значениями как целыми числами:

var scores map[string]int
Инициализировать карту

После объявления карты вам необходимо пройтиmakeфункцию для ее инициализации, чтобы ее можно было использовать:

scores = make(map[string]int)

Альтернативно вы можете использовать короткое объявление и инициализировать:

scores := make(map[string]int)

Вы также можете использовать литералы для инициализации во время объявления:

  1. scores := map[string]int{
  2. "alice": 90,
  3. "bob": 85,
  4. "charlie": 88,
  5. }

Особенности карты

  • ключевая уникальность: В карте каждый ключ уникален. Если вы попытаетесь вставить существующий ключ, оно обновит значение, соответствующее ключу.
  • беспорядок:map неупорядочен, и порядок элементов может меняться при каждой итерации карты.
  • динамический размер:Размер карты является динамическим, при необходимости вы можете добавлять или удалять пары ключ-значение.
  • ссылочный тип: Map — это ссылочный тип. Когда вы передаете карту в функцию, на самом деле вы передаете указатель на базовую структуру данных.

Карта операции

Добавить элемент
scores["alice"] = 90
Получить элемент
value := scores["alice"]

Если ключ не существует, будет возвращено нулевое значение для этого типа значения.

Проверьте, существует ли ключ

Вы можете использовать идиому запятая -ok, чтобы проверить, существует ли ключ на карте:

  1. value, exists := scores["alice"]
  2. if exists {
  3. // 键存在
  4. } else {
  5. // 键不存在
  6. }
Удалить элемент

использоватьdeleteФункция может удалить пару ключ-значение с карты:

delete(scores, "alice")

Если ключ не существует,deleteФункция ничего не делает.

Пройти карту

использоватьforЦикл может проходить по всем парам ключ-значение на карте:

  1. for key, value := range scores {
  2. fmt.Printf("%s: %dn", key, value)
  3. }

нулевое значение карты

Нулевое значение карты равноnil .одинnil Карта не имеет базовой структуры данных и не может добавлять элементы.Прежде чем добавлять элементы на карту, необходимо использоватьmakeИнициализируйте его.

длина карты

Вы можете использовать встроенныйlenФункция для получения количества пар ключ-значение на карте:

length := len(scores)

тип ключа карты

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

Легко совершать ошибки

В языке Go массивы, срезы и карты — это три часто используемые структуры данных, каждая из которых имеет разные характеристики и особенности. Вот несколько моментов, на которые следует обратить внимание при их использовании:

Множество

  • Избегайте использования слишком больших массивов, поскольку они занимают много места в стеке и могут привести к его переполнению.
  • Массивы используются, когда требуется коллекция данных фиксированного размера.

Кусочек

  • При расширении срезов может произойти перераспределение памяти. Постарайтесь заранее выделить достаточную емкость, чтобы избежать частого расширения.
  • Избегайте использования слишком больших фрагментов, поскольку они могут занимать много места в куче.
  • Обратите внимание, что нулевое значение среза равноnil, необходимо инициализировать перед использованием.

карта

  • Нулевое значение карты равноnilnilКарта не может использоваться для хранения пар ключ-значение и должна быть инициализирована перед использованием.
  • В параллельной среде операции чтения и записи на карте не являются потокобезопасными и должны быть защищены с помощью блокировок мьютексов или других механизмов синхронизации.
  • использоватьdeleteУдаление несуществующего ключа не вызывает ошибки, но можно безопасно проверить, существует ли ключ.