Ordenando com elegância no Go com o sort


A ordenação de elementos em um array é uma tarefa frequentemente utilizada em diversos programas. Embora existam muitos algoritmos de ordenação bem conhecidos, ninguém quer ficar copiando blocos de código de um projeto para outro.

Por isso, o Go oferece a biblioteca nativa sort.

Ela permite ordenar arrays in-place (a ordenação é feita diretamente na estrutura de dados original, sem criar uma cópia adicional do array) com qualquer critério de ordenação, utilizando uma abordagem baseada em interfaces.

A função sort.Sort não faz suposições sobre a estrutura dos dados; ela apenas exige que o tipo a ser ordenado implemente a interface sort.Interface, que define três métodos essenciais apresentados a seguir.


Um ótimo exemplo inicial é o tipo sort.StringSlice, fornecido pela própria biblioteca sort. Ele já implementa a interface sort.Interface, conforme mostrado abaixo:


Seguindo essas regras, é possível ordenar structs com base em seus campos como no exemplo a seguir, que ordena uma lista de alunos pela nota:


Com a estrutura já definida, também é possível verificar se o array está ordenado usando sort.IsSorted, além de realizar a ordenação em ordem reversa com sort.Reverse. As funções são demonstradas abaixo, utilizando a mesma estrutura do exemplo anterior.


A biblioteca também oferece outras funções bastante úteis:

  • Ints(x []int): ordena uma slice de inteiros em ordem crescente.
  • IntsAreSorted(x []int) bool: verifica se o slice x está ordenada em ordem crescente.
  • Strings(x []string): ordena um slice de strings em ordem crescente.
  • StringsAreSorted(x []string) bool: verifica se a slice x está ordenada em ordem crescente.


ATENÇÃO

Na própria documentação do pacote sort, na data de escrita deste artigo, existe uma nota na função sort.Sort que diz o seguinte:

Em muitas situações, a função mais recente slices.SortFunc é mais ergonômica e apresenta melhor desempenho.

Essa mesma nota se encontra na função sort.IsSorted:

Em muitas situações, a função mais recente slices.IsSortedFunc é mais ergonômica e apresenta melhor desempenho.

Em ambos os casos, recomendo avaliar qual abordagem adotar com base no que for mais vantajoso para a sua situação: a simplicidade das funções do pacote sort ou a possível otimização oferecida pelo pacote slices.

Para descobrir qual delas apresenta melhor desempenho no seu contexto, utilize os benchmarks do Go (fica aqui o dever de casa para você, caro leitor, dar uma conferida nisso).

A partir do Go 1.22, algumas funções do pacote sort já utilizam a biblioteca slices internamente, como é o caso de sort.Ints, que usa slices.Sort, e sort.IntsAreSorted, que usa slices.IsSorted.

Para saber mais, confira as documentações oficiais:

sort: https://pkg.go.dev/sort

slices: https://pkg.go.dev/slices


Referências:

DONOVAN, Alan A. A.; KERNIGHAN, Brian W.. The Go Programming Language. Crawfordsville: Addison-Wesley, 2016.

Documentação oficial da biblioteca sort: https://pkg.go.dev/sort

Documentação oficial da biblioteca slices: https://pkg.go.dev/slices