Раз срез отсортирован, все одинаковые значения лежат подряд.
Мы заводим индекс записи, который показывает на последний уникальный элемент, и одним проходом идём дальше по срезу. Как только встречаем значение, отличное от того, что уже записано, сдвигаем индекс записи и кладём туда новый элемент. Получается классический приём медленного и быстрого указателя, всё в один проход за O(n) и без дополнительной памяти.
В конце мы возвращаем срез, обрезанный по длине индекса записи.
func dedup[T comparable](s []T) []T {
if len(s) < 2 {
return s
}
w := 1
for i := 1; i < len(s); i++ {
if s[i] != s[w-1] {
s[w] = s[i]
w++
}
}
return s[:w]
}🐸 Библиотека Go для собеса