Как вставить элемент в слайс в Go

(последнее обновление от )

Классический паттерн (см. SliceTricks). Чтобы вставить x на позицию i и сохранить порядок:

a = append(a[:i+1], a[i:]...)
a[i] = x

Паттерн немного сложный для восприятия. На конкретном примере:

// a = [1, 2, 3, 4], вставляем 99 на позицию i=2
a = append(a[:3], a[2:]...)  // [1, 2, 3, 3, 4] — элемент 3 дублируется
a[2] = 99                    // [1, 2, 99, 3, 4]

Сложность O(n): весь хвост правее i сдвигается.

Часто встречается другой однострочник: append(a[:i], append([]T{x}, a[i:]...)...). Он короче, но хуже. Внутренний append создаёт временный слайс и копирует хвост лишний раз. Вариант выше сдвигает по месту, без лишней аллокации.

С Go 1.21 то же самое пишется проще:

a = slices.Insert(a, i, x)

Рекомендую использовать именно slices.Insert. Умеет вставлять несколько значений за один проход:

a = slices.Insert(a, i, x1, x2, x3)

В данном случае все три значения вставляются одним сдвигом хвоста, а не тремя. Для длинных слайсов разница будет ощутима.

Если есть потребность часто вставлять в середину большого слайса, то скорее всего нужна другая структура данных. Сложность вставки как O(n) будет влиять на производительность негативно.

Предыдущая заметка из серии — удаление элемента из слайса. Другие базовые темы собраны в дорожной карте по Go.


Теги: