Мы уже увидели, как создавать и работать с переменными, указателями и константами. В этой статье мы увидим четыре важных типа коллекций, встроенных в язык.
Мы начинаем с простых массивов, а затем переходим к Slice, усовершенствованной версии Array. В Slice мы говорим о сопоставлении коллекции пар ключ-значение. Начнем с массивов.
Множество
Как и в любом другом языке программирования, массив в Go представляет собой набор схожих типов данных фиксированного размера.
Объявление массива очень простое, как и любой другой язык, но с интересным поворотом,
other language syntax | Go syntax int[] arr = new int[10] | arr := [10]int
Левая часть объявления может показаться знакомой, если вы знакомы с программированием, например C # или Java. Единственное изменение в Go - мы указываем квадратные скобки с максимальным пределом перед типом данных массива.
Как и любое другое объявление переменной, массив также может быть объявлен инициализированным по-разному.
//Declaration 1 var arr = [5]int{1, 2, 3, 4, 5} //Declaration 2 var arr [5]int arr = [5]int{1, 2, 3, 4, 5} //Declaration arr := [5]int{1,2,3,4,5}
Массивы в Go индексируются с нуля, поэтому мы можем получить доступ к элементам массива, начиная с «0».
var arr [5]int arr[0] = 1 arr[1] = 2 fmt.Printf(arr[1]) //prints: 2
Кроме того, массивы в Go ограничены. Если вы попытаетесь получить доступ к элементу за пределами массива, Go выдаст ошибку времени выполнения.
var arr [5]int arr[0] = 1 arr[1] = 2 fmt.Printf(arr[6]) //Throws below compilation error invalid array index 6 (out of bounds for 5-element array)
Go также поддерживает многомерные массивы:
//Multi dimensional array var arrTwoD [2][3]int for i := 0; i < 2; i++ { for j := 0; j < 3; j++ { arrTwoD[i][j] = i + j } } fmt.Println("2d: ", arrTwoD) // prints: [[0 1 2] [1 2 3]]
Массивы фиксированной длины всегда жесткие для работы. Выделение памяти для массива происходит один раз при инициализации, что затрудняет увеличение или уменьшение размера массива в зависимости от размера данных. Массивы имеют лучшую скорость и производительность по сравнению со структурой данных, выделенной динамической памятью. Из-за жесткой природы массива в кодовых базах часто можно увидеть, что срезы используются чаще, чем массивы. Давайте посмотрим далее "Ломтики".
Кусочек
Срезы - это усовершенствованные версии массивов, построенных на основе массивов. В отличие от массивов, размер фрагмента может увеличиваться и уменьшаться в зависимости от размера данных. Гибкая природа Slice делает выбор в пользу массива, хотя последний имеет лучшую скорость и производительность по сравнению с первым.
Декларация
mySlice := []int{1, 2, 3}
Объявление среза довольно просто и похоже на объявление массива с той лишь разницей, что мы не указываем размер. Этого достаточно, чтобы компилятор понял разницу между массивом и срезом.
Динамическое изменение размера
Под капотом компилятор, увидев приведенное выше объявление, создает массив размером 3, добавляет элементы 1,2,3
в массив и указывает переменную mySlice
на массив. Нам не нужно иметь дело с базовым массивом самостоятельно. Вместо этого мы работаем только с переменной среза. Это может вызвать вопрос о том, чем срез отличается от массива, если он будет работать с массивом под капотом.
Как уже упоминалось, срез может динамически изменять размер. Давайте посмотрим на встроенный метод append()
, чтобы лучше в этом разобраться.
demoSlice := []int{1,2} fmt.Println(demoSlice) // [1,2] demoSlice = append(demoSlice,3) fmt.Println(demoSlice) // [1,2,3]
Таким образом, мы можем увеличить срез с помощью метода append()
. Go управляет базовым массивом, и это позволяет разработчику не беспокоиться о накладных расходах на изменение размера.
Кусочек ломтика
Оператор двоеточия :
в Go помогает в создании фрагмента фрагмента.
s1 := demoSlice[0:2]
- создает новый массив с элементами с индексом 0
до элемента перед индексом 2
. s1
содержит массив [1,2]
.
s2 := demoSlice[0:]
- создает новый массив с элементами с индексом 0
до конца среза. s2
содержит массив [1,2,3]
.
s3 := demoSlice[:2]
- создает новый массив с элементами от начала среза до элемента перед индексом 2
. s3
содержит массив [1,2]
.
Срезы - одна из мощных функций Go, дающая возможность динамически изменять их размер и создавать под-срезы, когда нам нужно работать с меньшими наборами данных.
карта
Карты - это коллекция, которая похожа на словарь или кучу в других языках программирования. Карты - это неупорядоченные коллекции, в которых данные хранятся в виде пар "ключ-значение". Карта используется для быстрого поиска, поиска значений на основе ключей и одной из часто используемых структур данных для ее производительности.
Карты являются изменяемыми типами данных, и их можно добавлять, изменять, а также удалять и очищать элементы.
Очень важно отметить, что Map - это неупорядоченная коллекция.
Декларация
var m map[--KeyType--]--ValueType--
// Example declaration
var demoMap1 map[int]string
demoMap2 := map[string]bool{}
Назначение и получение с карты
employeeMap := map[int]string{} //Assignment employeeMap[1] = "Employee 1" employeeMap[2] = "Employee 2" fmt.Println(employee) // map[1:Employee 1 2:Employee 2] //Retrieving data name := employeeMap[2] fmt.Println(employee[1]) //Employee 1 fmt.Println(name) //Employee 2
В отличие от некоторых языков программирования, Go не имеет каких-либо удобных функций для вывода списка ключей или значений карты. Однако он допускает итерацию с использованием оператора range
.
for key, value := range employeeMap {
fmt.Printf("%d is the key for the value %q\n", key, value)
}
Output:
2 is the key for the value "Employee 2"
1 is the key for the value "Employee 1"
Проверка наличия ключа на карте
Проверка наличия пары ключ-значение на карте - одна из очень удобных операций. Доступ к элементу на карте с помощью ключа возвращает два значения - value и bool. Возвращаемое значение bool поможет понять, доступен ли ключ на карте или нет.
name, ok := employeeMap[1]// Employee 1, true
name, ok := employees[1001]// "",false
Удаление
Для удаления значения из карты мы будем использовать встроенный метод delete
. Delete примет карту в качестве первого аргумента, а ключ значения, которое необходимо удалить, в качестве второго.
employeeMap := map[int]string{} //Assignment employeeMap[1] = "Employee 1" employeeMap[2] = "Employee 2" delete(employeeMap, 2) fmt.Println(employeeMap) Output: map[1:Employee 1]
Нет удобной функции для удаления всех элементов с карты.
employeeMap = map[int]string{}
fmt.Println(employeeMap)
Output
map[]
Карты состоят из пар "ключ-значение" и позволяют хранить данные, не полагаясь на индексацию. Это позволяет нам извлекать значения в зависимости от их значения и отношения к другим типам данных.
Заключение
Мы начали наше обсуждение с разговора о массивах и о том, как массивы представляют собой коллекцию фиксированного размера одного и того же типа сущностей. Таким образом, у вас могут быть массивы с целыми числами или массивы структурного типа. Любой тип данных, который у нас есть в Go, мы можем создать массив.
Затем мы перешли в обсуждение, чтобы поговорить о срезах и о том, как срезы во многих отношениях ведут себя как массивы, за исключением того, что срезы не являются объектами фиксированного размера. Размер фрагментов можно изменять по мере необходимости, и в результате они обычно используются вместо массивов, потому что возможность изменять их размер делает их намного более гибкими и открывает для них гораздо больше вариантов использования.
Затем мы поговорили о том, как мы можем связать ключи и значения вместе в типе коллекции, называемом картой в Go, и как мы можем создать эту карту, как мы можем добавлять сущности на эту карту и как мы можем извлекать сущности из нее.
Далее мы увидим структуры в Go. У нас нет концепции класса в Go. У нас есть методы и поля, но в этом языке они связаны гораздо более динамично и гибко. Посмотрим на это в следующей статье.
Ссылки и дополнительная литература: