Прогулка четвертая. Мегаполис и массивные строения

Goворить мы сегодня будем о массивах и о том, почему их лучше не использовать.

Массивы

Объявляют массивы так же как и другие переменные:

var a [128]byte // массив из 128 байт
var b [10][10]int // двумерный массив 10х10
var c [2] *int // массив из 2 указателей на целое

Но! В языке C массивы были элегантными и прекрасными. Время шло, массивы старели, их былая красота и грациозность канули в лету. В go массивы уже не узнать:

  • Массивы — это значения, не указатели. Если a и b — массивы, то a=b копирует все содержимое массива
  • Массивы сложно передавать в функции — они передаются по значению (фактически, копируются)
  • Размер массива тоже определяет его тип. Массивы «a [10]byte» и «b [20]byte» разных типов

Да, я говорил вам про указатели. Вы можете делать указатель на массив вида:

func f(a *[10]int) { ... }
f(&[10]int{1,2,3,4,5,6,7,8,9,10}) // Передаем указатель на массив

Но истинные go-кодеры так не делают. У них есть…

…Слайсы

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

Давайте разберем эту связь массива и слайса:

a := [5]int{1, 2, 3, 4, 5} // массив из пяти элементов. a[0] == 1, a[1] == 2 и т.д.
s := a[2:4] // а это уже слайс на основе массива a. Слайс начинается на 2м элементе, заканчивается на 4м
var p []int // неинициализированный слайс
p = s // теперь p указывает на то же место в массиве a, что и слайс s
q := a[3:] // это слайс, с 3-го до последнего элемента массива a.
a[3] = 13 // теперь s[1], p[1], q[0] стали равны 13

Возникает вопрос — неужели для каждого слайса необходимо создавать низлежащий массив? Нет. Для этого в go существует специальная функция make, создающая массив определенного размера и слайс с ним связанный. Функция выглядит примерно так:

s1 := make([]int, 5) // создает слайс, вмещающий 5 целых чисел
s2 := make([]int, 5, 10) // создает слайс на 5 чисел, построенный над массивом на 10 элементов

Размер имеет значение

В go для определения размеров есть две функции — len() и cap(). Раз функции две, то они должны отличаться. Вот в чем разница:

  • len(x) используют, чтобы получить: длину строки, размер массива, размер слайса
  • cap(x) возвращает: размер массива (аналогично len), максимальный размер слайса и другие вещи, о которых вы еще не знаете

Как видите, для слайсов cap и len отличаются. Оказывается len возвращает текущий размер слайса, а cap — его размер плюс размер «хвоста» массива (данных, идущих в массиве после слайса) — на эти данные слайс может быть расширен.

a [5]int{1,2,3,4,5}
s = a[1:3] // слайс указывает на {2,3,4}
// тогда:
// len(s) == 3
// cap(s) == 4

Для нулевых слайсов (nil) len() вернет ноль, равно как и cap().

Для копирования слайсов, кстати, есть функция copy(dst, src). Области могут перекрывать друг друга:

a := [5]int{1,2,3,4,5}
s := a[1:] // s==[]int{2,3,4,5}
n := copy(s, s[1:]) // вернет кол-во скопированных эл-тов (три). s == []int{3,4,5,5}

Все. Пробуйте. В новом языке нет ничеGO сложноGO!


Домашнее задание

  • Нахождение суммы чисел в массиве
  • Нахождение максимума/минимума/среднего среди чисел в массиве
  • Нахождение максимальной восходящей последовательности в массиве
  • Ну, и конечно же, сортировка массива!
Реклама

One comment on “Прогулка четвертая. Мегаполис и массивные строения

  1. locky37:

    Спасибо за статью.

    А где google +1 )

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s