2016-11-04 2 views
0

Я читаю A Tour of Go и запутаться в случае нарезанияпочему емкость Срез не уменьшается с `[: 0]`

s = s[:0] 

После этой операции len() из s становится равным 0, но cap() не , Почему емкость не уменьшается? Когда вы захотите использовать эту «особенность»?

+2

предположим, что вы используете этот срез как стек, который растет и сжимается. вы вытащили последний элемент из стека, это len равно 0. Теперь вы нажимаете на него некоторые элементы. производительность будет катастрофической, если в этом случае нам нужно будет снова распределять и наращивать мощности. –

+2

Вот использование '[: 0]': [Запись в начало буфера в Голанге?] (Http://stackoverflow.com/a/40234309/1705598) Связано также: [Объединить два фрагмента в Go] (http : //stackoverflow.com/a/40036950/1705598) – icza

+1

Отличный вопрос! Следующее сообщение в блоге также стоит прочитать: https://blog.golang.org/go-slices-usage-and-internals –

ответ

3

Возможность не изменять мощность, вероятно, является оптимизацией производительности. Ломтики - это в основном «динамические массивы», они намереваются предоставить абстракцию, что емкость массива неограничена. На самом деле, емкость, конечно, ограничена системной памятью, однако, если ломтик имеет емкость, и вы можете указать элемент для него, Go будет выделять новую память для массива, чтобы обеспечить эту емкость (при условии, что она доступна, если это не ваше приложение из паники).

Длина представляет собой фактическое индексируемое количество элементов в срезе, тогда как емкость указывает вам, какая у него основная память. Когда вы выполняете эти операции reslicing, нет необходимости немедленно освобождать память, и поэтому она остается выделенной, поэтому емкость срезов остается неизменной, но длина равна нулю.

В целом, это, вероятно, приводит к повышению производительности приложений, так как память все еще доступна, если последующие утверждения присоединяют элементы к срезу. На практике вам вообще не нужно беспокоиться о емкости. Я бы рекомендовал держать его в задней части вашего разума.

Время, когда это наиболее актуально, imo, это когда вы читаете данные из какого-то источника, и знаете размер этих данных или, по крайней мере, имеете приблизительную идею, и вы помещаете это в кусочек. В таком случае ваше приложение будет работать лучше, если вы инициализируете срез с соответствующей емкостью. Если вы не указываете аргументы длины или емкости (емкость по умолчанию равна длине, если предоставляется только длина), вы можете обнаружить, что рост среза по умолчанию довольно неэффективен или, по крайней мере, представляет собой неэффективность, которую можно легко избежать.

4

Вы можете использовать трехиндексную нарезку, чтобы получить нулевой колпачок среза:

s = s[:0:0] 

Экспозицию: https://play.golang.org/p/YetCdJVWrB.

Смежные вопросы