Algoritmos e Estruturas de Dados em Go: Guia Prático
\n\nGo (Golang) é uma linguagem compilada e estaticamente tipada, criada no Google. Sua simplicidade, alto desempenho e suporte nativo a concorrência a tornam uma excelente escolha para desenvolvimento backend, microsserviços e programação de sistemas. No entanto, para escrever código eficiente em Go, não basta conhecer a sintaxe — é necessário entender como funcionam os algoritmos e as estruturas de dados. Neste artigo, abordaremos as principais estruturas de dados e algoritmos em Go, fornecendo exemplos práticos em cada seção.
\n\n1. Pilha (Stack) em Go
\n\nUma pilha é uma estrutura de dados que opera pelo princípio LIFO (Last In, First Out). Em Go, não existe um tipo "pilha" nativo, mas é fácil implementá-la usando uma fatia (slice).
\n\nExemplo de implementação de pilha:
\n\npackage main\n\nimport "fmt"\n\ntype Stack struct {\n items []int\n}\n\n// Push adiciona um elemento ao topo da pilha\nfunc (s *Stack) Push(item int) {\n s.items = append(s.items, item)\n}\n\n// Pop remove e retorna o elemento do topo da pilha\nfunc (s *Stack) Pop() (int, bool) {\n if len(s.items) == 0 {\n return 0, false\n }\n lastIndex := len(s.items) - 1\n item := s.items[lastIndex]\n s.items = s.items[:lastIndex]\n return item, true\n}\n\n// Peek retorna o elemento do topo sem removê-lo\nfunc (s *Stack) Peek() (int, bool) {\n if len(s.items) == 0 {\n return 0, false\n }\n return s.items[len(s.items)-1], true\n}\n\nfunc main() {\n stack := Stack{}\n stack.Push(10)\n stack.Push(20)\n stack.Push(30)\n\n item, ok := stack.Pop()\n if ok {\n fmt.Println("Removido:", item) // 30\n }\n fmt.Println("Topo da pilha:", stack.Peek()) // 20\n}\n\nA pilha em Go é eficiente devido à complexidade amortizada O(1) para as operações Push e Pop. Use-a para tarefas como verificação de sequências de parênteses ou desfazer ações (undo).
\n\n2. Fila (Queue) em Go
\n\nUma fila opera pelo princípio FIFO (First In, First Out). Vamos implementá-la usando uma fatia com ponteiros para o início e o fim.
\n\nExemplo de implementação de fila:
\n\npackage main\n\nimport "fmt"\n\ntype Queue struct {\n items []int\n}\n\n// Enqueue adiciona um elemento ao final da fila\nfunc (q *Queue) Enqueue(item int) {\n q.items = append(q.items, item)\n}\n\n// Dequeue remove e retorna o elemento do início da fila\nfunc (q *Queue) Dequeue() (int, bool) {\n if len(q.items) == 0 {\n return 0, false\n }\n item := q.items[0]\n q.items = q.items[1:]\n return item, true\n}\n\n// Front retorna o primeiro elemento sem removê-lo\nfunc (q *Queue) Front() (int, bool) {\n if len(q.items) == 0 {\n return 0, false\n }\n return q.items[0], true\n}\n\nfunc main() {\n queue := Queue{}\n queue.Enqueue(1)\n queue.Enqueue(2)\n queue.Enqueue(3)\n\n item, ok := queue.Dequeue()\n if ok {\n fmt.Println("Removido:", item) // 1\n }\n fmt.Println("Primeiro na fila:", queue.Front()) // 2\n}\n\nAtenção: a operação Dequeue nesta implementação tem complexidade O(n), pois a remoção do primeiro elemento desloca toda a fatia. Para código em produção, use um buffer circular (ring buffer) ou uma lista duplamente encadeada (container/list).
3. Ordenação por Bolha (Bubble Sort) em Go
\n\nA ordenação por bolha é um dos algoritmos mais simples, porém ineficientes. No entanto, é excelente para aprendizado. Complexidade: O(n²).
\n\npackage main\n\nimport "fmt"\n\nfunc bubbleSort(arr []int) {\n n := len(arr)\n for i := 0; i < n-1; i++ {\n swapped := false\n for j := 0; j < n-i-1; j++ {\n if arr[j] > arr[j+1] {\n arr[j], arr[j+1] = arr[j+1], arr[j]\n swapped = true\n }\n }\n // Se não houve trocas — o array já está ordenado\n if !swap