После чтения данного урока вы сможете:
- В случае необходимости использовать срез массива;
- Упорядочить срезы в алфавитном порядке через стандартную библиотеку.
Содержание статьи
- Срез массива в Golang
- Индексы для среза по умолчанию
- Срез строк в Golang
- Композитные литералы для срезов
- Преимущества среза массива в Golang
- Срезы с методами в Golang
Планеты нашей Солнечной системы принято классифицировать на планеты земной группы, газовые гиганты и ледяные гиганты. Ниже дается схема. Пока что можем сфокусироваться на земной группе, отрезав первые четыре элементы массива planets
через planets[0:4]
. Срез не изменяет массив planets
. Он просто создает своеобразное окно, или вид внутрь массива. Данный вид называют срезом.
![](https://golangify.com/wp-content/uploads/2020/04/go-read.png)
Рекомендуем вам супер 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
.
![](https://golangify.com/wp-content/uploads/2021/01/v.jpg)
Администрирую данный сайт с целью распространения как можно большего объема обучающего материала для языка программирования 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 возвращает не срез, а строку.