Если вы программируете на 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]

Вы можете запустить образец кода, нажав здесь

Следите за новостями, скоро мы узнаем больше советов по голангу…