Модифицируют ли стандартные функции сортировки исходный слайс?

Ответ

Да, все функции сортировки из стандартного пакета sort (например, sort.Ints, sort.Strings, sort.Slice) модифицируют исходный слайс, работая "на месте" (in-place).

Почему так происходит?

Слайс в Go — это легковесная структура-дескриптор, которая содержит три поля:

  1. Указатель на начало нижележащего массива (underlying array).
  2. Длину (length).
  3. Ёмкость (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]