Если вы программируете на Golang, то, вероятно, много работали со срезами, так как это отличная особенность языка. Я уверен, что вы манипулировали срезами по-разному. Так я и сделал. Недавно я обнаружил очень интересную особенность языка, которая заставила меня немного по-другому работать со срезами.
Предположим, у вас есть следующий фрагмент:
s1 := []string{"one", "two", "three", "four", "five"}
и вы хотите получить первые два элемента. Вы можете просто сделать:
s2 := s1[:2]
Если мы попытаемся распечатать содержимое этих двух фрагментов, мы, вероятно, получим следующее:
fmt.Printf("%+v\n", s1) fmt.Printf("%+v\n", s2) [one two three four five] [one two]
Пока все хорошо, ничего особенного. Давайте попробуем создать еще один фрагмент и посмотреть его содержимое следующим образом:
s3 := s2[:len(s2)] fmt.Printf("%+v\n", s3) [one two]
Опять ожидал. Новый срез s3
назначается для включения первого s2
element до последнего, поэтому он должен выводить то же самое, что и s2
. А теперь попробуем следующее. Давайте попробуем назначить другому s4
срезу элементы от s2
, начиная с первого элемента до…. емкость срезаs2
.
s4 := s2[:cap(s2)] fmt.Printf("%+v\n", s4) [one two three four five]
Ух ты!! Итак, s2
знает намного больше, чем мы ожидали. На самом деле он знает все элементы фрагмента s1
, хотя, когда мы его создавали, мы сказали языку, чтобы он разрезал его по-другому. Это происходит потому, что s2
, s1
и все последующие срезы используют одни и те же указатели памяти. Все они указывают на один и тот же (начальный) срез. Но что, если мы действительно хотим получить чистую копию среза, не неся все данные исходного?
Вместо s2 := s1[:2]
давайте сделаем следующее. Мы инициализируем новый срез длиной 2 и копируем первые два элемента s1
в инициализированный s2
срез. Если мы попытаемся получить срез, как мы делали до использования емкости, и распечатать его, мы увидим следующий результат, который означает, что s2
срез теперь указывает на новый срез, который содержит только первые два элемента s1
s2 := make([]string, 2) copy(s2, s1[:2]) s4 := s2[:cap(s2)] fmt.Printf("%+v\n", s4) [one two]
Вы можете запустить образец кода, нажав здесь
Следите за новостями, скоро мы узнаем больше советов по голангу…