Когда жизнь дает тебе лимоны

Головоломка

Как вы думаете, что напечатает следующая программа?

Эта программа напечатает:

cart: [apple pear lemon] fruits: [apple pear lemon]

Добавление к fruits затронуло и cart. Этот результат связан с тем, как в Go построены слайсы.

Если вы посмотрите на slice.go, вы увидите следующее определение:

  • arrayэто указатель на базовый массив данных, на который смотрит срез
  • len - это количество элементов, на которые смотрит срез.
  • cap — это количество элементов от array до конца базового массива.

В нашем случае, прежде чем мы добавим к fruits, данные выглядят так:

И cart, и fruits указывают на один и тот же базовый массив. Когда вы добавляете к fruits, Go будет искать, есть ли больше места в базовом массиве; если есть — он будет использовать это пространство. В противном случае Go выделит новый массив большего размера. Скопируйте данные, а затем добавьте.

Вот пример реализации append для целых чисел:

В нашем случае fruits имеет еще одно место в базовом массиве. appendбудет использовать тот же базовый массив, на который смотрит cart.

Если вы напечатаете lenи cap перед добавлением:

Ты увидишь:

Как это исправить? Вы можете использовать выражение полного среза:

И теперь вы получите:

cart: [apple pear milk] fruits: [apple pear lemon]

Теперь, когда вы печатаете len и cap перед добавлением:

Ты увидишь:

Так как емкость fruits равна 2, Go выделит и скопирует. Теперь поле array cart и fruits указывает на разные массивы.

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



Мики Тебека
Будьте в курсе статей, книг и других материалов Мики Вамекиmedium.com



Если вам нравится решать задачи по программированию, ознакомьтесь с книгами Мики Тебека «Дразнилки для ума» на The Pragmatic Bookshelf. Вы можете сэкономить 35% на электронных версиях книг с промокодом brain_teasers_35 до 31 октября 2022 года: