После чтения данного урока вы сможете:
- В случае необходимости использовать срез массива;
- Упорядочить срезы в алфавитном порядке через стандартную библиотеку.
Содержание статьи
- Срез массива в Golang
- Индексы для среза по умолчанию
- Срез строк в Golang
- Композитные литералы для срезов
- Преимущества среза массива в Golang
- Срезы с методами в Golang
Планеты нашей Солнечной системы принято классифицировать на планеты земной группы, газовые гиганты и ледяные гиганты. Ниже дается схема. Пока что можем сфокусироваться на земной группе, отрезав первые четыре элементы массива planets
через planets[0:4]
. Срез не изменяет массив planets
. Он просто создает своеобразное окно, или вид внутрь массива. Данный вид называют срезом.
Рекомендуем вам супер TELEGRAM канал по Golang где собраны все материалы для качественного изучения языка. Удивите всех своими знаниями на собеседовании! 😎
Мы публикуем в паблике ВК и Telegram качественные обучающие материалы для быстрого изучения Go. Подпишитесь на нас в ВК и в Telegram. Поддержите сообщество Go программистов.
Срез Солнечной системы
У вас есть какие-то коллекции? Они организованы в определенном порядке? К примеру, книги на полке могут быть рассортированы по фамилиям автора. Упорядочивание подобного рода помогает ориентироваться и быстро книги.
Таким же образом вы можете также использовать срезы к нулю как часть коллекции.
Срез массива в Golang
Срез выражается через наполовину открытый диапазон. В следующем примере planets[0:4]
начинается с планеты с индексом 0, продолжается, но не включает планету с индексом 4.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
planets := [...]string{ "Меркурий", "Венера", "Земля", "Марс", "Юпитер", "Сатурн", "Уран", "Нептун", } terrestrial := planets[0:4] gasGiants := planets[4:6] iceGiants := planets[6:8] fmt.Println(terrestrial, gasGiants, iceGiants) // Выводит: [Меркурий Венера Земля Марс] [Юпитер Сатурн] [Уран Нептун] |
Хотя terrestrial
, gasGiants
и iceGiants
являются срезами, вы по-прежнему можете получать значение по индексу внутри срезов, как и внутри массивов:
1 |
fmt.Println(gasGiants[0]) // Выводит: Юпитер |
Вы также можете разрезать массив, а потом полученный срез разрезать еще раз:
1 2 3 4 |
giants := planets[4:8] gas := giants[0:2] ice := giants[2:4] fmt.Println(giants, gas, ice) // Выводит: [Юпитер Сатурн Уран Нептун] [Юпитер Сатурн] [Уран Нептун] |
Срезы terrestrial
, gasGiants
, iceGiants
, giants
, gas
и ice
являются видами одного и того же массива planets
. Присваивание нового значения к элементу среза меняет базовый массив planets
. Изменение будет видно и в других срезах:
1 2 3 4 |
iceGiantsMarkII := iceGiants // Копирует срез iceGiants (вид массива planets) iceGiants[1] = "Посейдон" fmt.Println(planets) // Выводит: [Меркурий Венера Земля Марс Юпитер Сатурн Уран Посейдон] fmt.Println(iceGiants, iceGiantsMarkII, ice) // Выводит: [Уран Посейдон] [Уран Посейдон] [Уран Посейдон] |
Вопросы для проверки:
- Что получается в результате разреза массива?
- При разрезе через
planets[4:6]
сколько элементов получится в конечном итоге?
Индексы для среза по умолчанию
При разрезе массива пропуск первого индекса равнозначен указанию начала массива, а пропуск последнего индекса — длине массива. Таким образом, разрез в Листинге 1 можно написать и так:
1 2 3 |
terrestrial := planets[:4] gasGiants := planets[4:6] iceGiants := planets[6:] |
Обратите внимание, что индексы среза не могут быть отрицательными.
К чему приводит пропуск обоих индексов? Переменная allPlanets
является срезом, который теперь содержит все восемь планет:
1 |
allPlanets := planets[:] |
Срез строк в Golang
Синтаксис среза массива также можно использовать для строк:
1 2 3 |
neptune := "Neptune" tune := neptune[3:] fmt.Println(tune) // Выводит: tune |
Результатом среза строки является другая строка. Однако, присваивание нового значения neptune
не изменит значения tune
и наоборот:
1 2 |
neptune = "Poseidon" fmt.Println(tune) // Выводит: tune |
Имейте в виду, что индексы учитывают количество байтов, но не рун:
1 2 |
question := "¿Cómo estás?" fmt.Println(question[:6]) // Выводит: ¿Cóm |
Вопрос для проверки:
Если бы Земля и Марс были единственными колонизированными планетами, как бы вы могли получить срез colonized
от terrestrial
?
Композитные литералы для срезов
Многие функции Go лучше оперируют со срезами, чем с массивами. Если вам нужен срез, что показывает каждый элемент базового массива, можно объявить массив, а затем сделать срез через [:]
. Это делается следующим образом:
1 2 |
dwarfArray := [...]string{"Церера", "Плутон", "Хаумеа", "Макемаке", "Эрида"} dwarfSlice := dwarfArray[:] |
Разрез массива является одним из способов создания среза, однако вы также можете объявить срез напрямую. У среза строк тип []string
, внутри квадратных скобок нет никакого значения. Это отличается от объявления массива, где всегда уточняется фиксированная длина или многоточие внутри квадратных скобок.
В следующем примере срез dwarfs
инициализируется через уже знакомый синтаксис композитного литерала:
1 |
dwarfs := []string{"Церера", "Плутон", "Хаумеа", "Макемаке", "Эрида"} |
Базовый массив по-прежнему существует. Незаметно, Go сам объявляет массив из пяти элементов, а затем делает срез, что показывает все элементы.
Задание для проверки:
Используйте специальный символ %T
для сравнения типов dwarfArray
и среза dwarfs
.
Преимущества среза массива в Golang
Представьте, что существует способ преодолеть преграды пространства и времени, что позволяет объединять миры и путешествовать в мгновение ока? Использование стандартной библиотеки Go в совокупности с некоторой изобретательностью позволяет функции hyperspace
из Листинга 4 модифицировать срез worlds
, убрав отступы между мирами разных планет.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package main import ( "fmt" "strings" ) // hyperspace убирает отступы между мирами планет func hyperspace(worlds []string) { // Данный аргумент является срезом, а не массивом for i := range worlds { worlds[i] = strings.TrimSpace(worlds[i]) } } func main() { planets := []string{" Венера ", "Земля ", " Марс"} // Планеты, разделенные друг от друга пробелами hyperspace(planets) fmt.Println(strings.Join(planets, "")) Выводит: ВенераЗемляМарс } |
Оба worlds
и planets
являются срезами, и хотя worlds
представляет собой копию, они оба указывают на один и тот же базовый массив.
Если бы hyperspace
изменил точки начала или конца среза worlds
, данные изменения не оказали бы никакого влияния на срез planets
. Однако hyperspace
может достигнуть базового массива, на который указывает worlds
, и изменить его элементы. Данные изменения доступны другим срезам (видам) массива.
Срезы более изменчивые, нежели массивы и в других аспектах. У срезов есть длина, однако, в отличие от длины массивов, она не является частью типа. Вы можете передать срез любого размера функции hyperspace
:
1 2 |
dwarfs := []string{" Церера ", " Плутон"} hyperspace(dwarfs) |
Массивы редко используются напрямую. Разработчики Go предпочитают срезы ввиду их гибкости, особенно при передачи аргументов функции.
Вопрос для проверки:
Просмотрите документацию Go, отыщите TrimSpace
и Join
. Какую функциональность они предоставляют?
Срезы с методами в Golang
В Go можно определить тип через базовый слайс или массив. При наличии типа вы можете закрепить за ним метод. Способность Go объявлять методы типам доказывает их многогранность по сравнению с классами в других языках.
Пакет sort
стандартной библиотеки объявляет тип StringSlice
:
1 |
type StringSlice []string |
К StringSlice
прикрепляется метод Sort
:
1 |
func (p StringSlice) Sort() |
Для упорядочивания планет в алфавитном порядке в следующем примере planets
конвертируется в тип sort.StringSlice
, а затем вызывается метод Sort
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package main import ( "fmt" "sort" ) func main() { planets := []string{ "Меркурий", "Венера", "Земля", "Марс", "Юпитер", "Сатурн", "Уран", "Нептун", } sort.StringSlice(planets).Sort() // Сортирует planets в алфавитном порядке fmt.Println(planets) // Выводит: [Венера Земля Марс Меркурий Нептун Сатурн Уран Юпитер] } |
В пакете sort
есть вспомогательная функция Strings
для конвертации типа и вызова метода Sort
. Это значительно облегчает процесс:
1 |
sort.Strings(planets) |
Вопрос для проверки:
Что делает sort.StringSlice(planets)
?
Заключение
- Срез можно назвать окном, или видом в массив;
- Ключевое слово
range
может итерировать через срезы; - Срезы разделяют одинаковую базовую информацию во время присваивания или передачи другим функциям;
- Композитные литералы предоставляют удобные способы для инициализации срезов;
- Вы можете прикрепить методы к срезам.
Итоговое задание для проверки:
Напишите программу для преобразования слайса строки через добавление слова "Новый "
перед названием планеты. Используйте программу для изменения названий планет Марс
, Уран
и Нептун
.
В первой итерации может использоваться функция terraform
, но в конечной реализации должен быть введен тип Planets
с методом terraform
, похожим на sort.StringSlice
.
Администрирую данный сайт с целью распространения как можно большего объема обучающего материала для языка программирования Go. В IT с 2008 года, с тех пор изучаю и применяю интересующие меня технологии. Проявляю огромный интерес к машинному обучению и анализу данных.
E-mail: vasile.buldumac@ati.utm.md
Образование
Технический Университет Молдовы (utm.md), Факультет Вычислительной Техники, Информатики и Микроэлектроники
- 2014 — 2018 Universitatea Tehnică a Moldovei, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Universitatea Tehnică a Moldovei, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»
У вас ошибка в ответах на вопросы пункта «Преимущества среза массива в Golang». TrimSpace возвращает не срез, а строку.