Código da aula: Github
Introdução
Na Aula 43, exploramos os conceitos básicos de ordenação em Go, utilizando o pacote sort e a implementação da interface sort.Interface.
Aprendemos como ordenar slices de tipos comuns como números inteiros, strings e structs personalizadas, utilizando funções pré-definidas e personalizadas do pacote sort.
Nesta aula, vamos expandir esses conceitos, mergulhando mais profundamente na ordenação customizada em Go.
Utilizaremos o pacote slices para aplicar funções de comparação personalizadas que atendem a requisitos específicos, permitindo a ordenação de estruturas mais complexas e tipos de dados que não são inerentemente ordenáveis pela sua natureza.
Vamos explorar casos de uso mais avançados e específicos, como a ordenação de logs por nível de severidade, atividades por duração e itens de menu por calorias.
Ordenação de Logs por Nível de Severidade
Logs de sistemas podem ter vários níveis de severidade, como INFO, WARN, e ERROR. Podemos querer ordenar esses logs para processar ou exibir primeiro os mais críticos.
package main
import (
"fmt"
"slices"
)
type LogEntry struct {
timestamp string
severity string
message string
}
// Definindo uma ordem de severidade
var severityOrder = map[string]int{
"INFO": 1,
"WARN": 2,
"ERROR": 3,
}
func main() {
logs := []LogEntry{
{"2024-01-10 14:00", "INFO", "System started"},
{"2024-01-10 14:01", "ERROR", "Failed to load module"},
{"2024-01-10 14:02", "WARN", "Memory usage high"},
}
severityCmp := func(a, b LogEntry) int {
return severityOrder[a.severity] - severityOrder[b.severity]
}
slices.SortFunc(logs, severityCmp)
fmt.Println("Logs sorted by severity:", logs)
}
LogEntry: É uma struct que representa uma entrada de log, contendo:
timestamp: A data e hora em que o log foi registrado.
severity: O nível de severidade do log (ex.: INFO, WARN, ERROR).
message: A mensagem do log.
severityOrder: É um mapa que define uma ordem numérica para cada nível de severidade, sendo útil para comparar e ordenar os logs baseado em sua severidade.
logs: É um slice que contém várias instâncias da struct LogEntry, representando diferentes entradas de log.
severityCmp: É uma função de comparação. Ela recebe dois argumentos a e b do tipo LogEntry e retorna um inteiro. A função compara os logs a e b com base nos valores de seus níveis de severidade conforme definido no mapa severityOrder.
- Se
a é menos severo que b, retorna um valor negativo.
- Se
a é mais severo que b, retorna um valor positivo.
- Se são igualmente severos, retorna zero.
slices.SortFunc(logs, severityCmp): Esta linha chama a função SortFunc do pacote slices, passando o slice logs e a função de comparação severityCmp como argumentos. SortFunc ordena o slice logs in-place (modifica o próprio slice) de acordo com a ordem de severidade definida.
fmt.Println: Imprime o slice de logs ordenado por severidade.
Ordenação de Atividades por Duração
Em um aplicativo de gerenciamento de tempo, podemos querer ordenar atividades por duração para identificar as que consomem mais tempo.
package main
import (
"fmt"
"slices"
"time"
)
type Activity struct {
name string
duration time.Duration
}
func main() {
activities := []Activity{
{"Read email", 15 * time.Minute},
{"Meeting", 2 * time.Hour},
{"Code review", 45 * time.Minute},
}
durationCmp := func(a, b Activity) int {
if a.duration < b.duration { return -1 } else if a.duration > b.duration {
return 1
}
return 0
}
slices.SortFunc(activities, durationCmp)
fmt.Println("Activities sorted by duration:", activities)
}
Activity: Uma struct que representa uma atividade, contendo:
name: O nome da atividade.
duration: A duração da atividade, armazenada como uma variável do tipo time.Duration, que é uma representação de duração em nanosegundos.
activities: Um slice que contém instâncias da struct Activity, representando diferentes atividades com suas respectivas durações.
durationCmp: Uma função de comparação que define como as atividades serão ordenadas com base em sua duração.
- Se a duração da atividade
a for menor que a de b, a função retorna -1, indicando que a deve vir antes de
- Se a duração da atividade
a for maior que a de b, retorna 1, indicando que a deve vir depois de b.
- Se as durações forem iguais, retorna
0, indicando que a ordem relativa de a e b pode ser qualquer.
slices.SortFunc(activities, durationCmp): Esta chamada usa a função SortFunc do pacote slices, passando o slice activities e a função de comparação durationCmp como argumentos. SortFunc ordena o slice activities in-place (modifica o próprio slice) conforme definido pela função durationCmp.
fmt.Println: Imprime o slice de atividades ordenadas por duração.
Ordenação de Itens de Menu por Calorias
Em um app de nutrição, a ordenação de itens de menu por calorias pode ajudar os usuários a escolher alimentos mais saudáveis.
package main
import (
"fmt"
"slices"
)
type MenuItem struct {
name string
calories int
}
func main() {
menu := []MenuItem{
{"Salad", 200},
{"Cheeseburger", 700},
{"Smoothie", 300},
}
caloriesCmp := func(a, b MenuItem) int {
return a.calories - b.calories
}
slices.SortFunc(menu, caloriesCmp)
fmt.Println("Menu items sorted by calories:", menu)
}
MenuItem: Uma struct que representa um item de menu, contendo:
name: O nome do item de menu.
calories: A quantidade de calorias que o item contém.
menu: Um slice de MenuItem, que contém três itens de menu diferentes com suas respectivas calorias.
caloriesCmp: Uma função de comparação definida para comparar dois itens de menu com base em suas calorias.
- Se o resultado da subtração
a.calories - b.calories for negativo, indica que a tem menos calorias que b e deve vir antes na ordenação.
- Se for positivo,
a tem mais calorias que b e deve vir depois.
- Se for zero, significa que ambos os itens têm igual quantidade de calorias e sua ordem relativa na lista pode permanecer a mesma.
slices.SortFunc(menu, caloriesCmp): Utiliza a função SortFunc do pacote slices para ordenar o slice menu in-place (modificando o próprio slice) de acordo com a função de comparação caloriesCmp.
fmt.Println: Imprime o resultado final do slice menu após a ordenação, mostrando os itens de menu ordenados por sua quantidade de calorias.
Conclusão
Nesta aula, exploramos diferentes maneiras de aplicar funções de comparação personalizadas para ordenar tipos de dados complexos e específicos.
Esses exemplos mostram como a ordenação customizada pode ser utilizada em aplicações do mundo real, aumentando a eficiência e a utilidade dos dados.
Vimos como ordenar logs por nível de severidade, atividades por duração e itens de menu por calorias, demonstrando a versatilidade e o poder das funções personalizadas no Go.
Lembre-se de explorar mais sobre as funções de comparação e continuar praticando para dominar a ordenação em seus projetos Go!
Na próxima aula, vamos mudar um pouco o foco para um tópico fundamental no tratamento de erros em Go: o uso da função
panic.
Veremos como e quando utilizar
panic para falhas que não podem ser tratadas de maneira convencional e como isso se aplica ao design robusto de programas em Go.