Ответ
Да, все функции сортировки из стандартного пакета sort
(например, sort.Ints
, sort.Strings
, sort.Slice
) модифицируют исходный слайс, работая "на месте" (in-place).
Почему так происходит?
Слайс в Go — это легковесная структура-дескриптор, которая содержит три поля:
- Указатель на начало нижележащего массива (underlying array).
- Длину (length).
- Ёмкость (capacity).
Когда вы передаете слайс в функцию, копия этого дескриптора создается, но указатель в копии указывает на тот же самый массив в памяти. Поэтому функция сортировки, изменяя элементы по этому указателю, модифицирует данные в оригинальном массиве, что и видит исходный слайс.
Пример:
package main
import (
"fmt"
"sort"
)
func main() {
numbers := []int{3, 1, 4, 1, 5, 9, 2, 6}
fmt.Println("Оригинал:", numbers)
sort.Ints(numbers) // Сортировка на месте
fmt.Println("После сортировки:", numbers) // Вывод: [1 1 2 3 4 5 6 9]
}
Как отсортировать, не изменяя оригинал?
Чтобы сохранить исходный слайс, необходимо сначала создать его копию, а затем сортировать уже её.
Способ 1: Классический (с помощью copy
)
original := []int{3, 1, 4}
sortedCopy := make([]int, len(original))
copy(sortedCopy, original)
sort.Ints(sortedCopy) // original останется [3, 1, 4]
Способ 2: Современный (Go 1.21+ с пакетом slices
)
import "slices"
original := []int{3, 1, 4}
sortedCopy := slices.Clone(original)
sort.Ints(sortedCopy) // original останется [3, 1, 4]