Como remover um elemento de um Slice em Golang: guia detalhado com exemplos
\n\nTrabalhar com slices em Go é uma rotina diária de todo desenvolvedor. Mas uma operação gera dúvidas até mesmo em "gophers" experientes: remover um elemento de um slice. Parece simples, não? No entanto, Go não possui um método embutido delete() para slices, como tem para maps. É preciso reinventar a roda.
Neste artigo, abordaremos todas as formas de remover um elemento de um slice em Golang: desde a remoção simples por índice até truques avançados com preservação da ordem e otimização de memória. Você aprenderá como funciona a mecânica interna dos slices, por que a simples atribuição nem sempre funciona e como evitar erros típicos.
\n\nPor que Go não tem uma função embutida para remover de um slice?
\n\nAntes de mergulhar no código, vamos entender a filosofia da linguagem. Um slice em Go é apenas uma "janela" para o array subjacente. Ele não possui os dados, apenas faz referência a eles. Portanto, remover um elemento não é apagar fisicamente os dados da memória (como em C++), mas sim reconstruir a "janela" usando operações engenhosas de append e slicing.
Go permite que você decida como organizar a remoção: com ou sem preservação da ordem, com ou sem redução da capacidade. Isso oferece flexibilidade, mas exige compreensão.
\n\nMétodo 1: Remoção por índice (com preservação da ordem)
\n\nEste é o caso mais comum. Você tem um slice e deseja remover o elemento na posição i, mantendo a ordem relativa dos demais elementos.
package main\n\nimport "fmt"\n\nfunc removeIndex(s []int, index int) []int {\n // Junta a parte antes do índice com a parte depois do índice\n return append(s[:index], s[index+1:]...)\n}\n\nfunc main() {\n slice := []int{1, 2, 3, 4, 5}\n slice = removeIndex(slice, 2) // remove o elemento no índice 2 (valor 3)\n fmt.Println(slice) // [1 2 4 5]\n}\n\n\nComo funciona?
\n- \n
s[:index]— pega todos os elementos até o removido (excluindo-o). \n s[index+1:]— pega todos os elementos após o removido. \n appendcombina essas duas "partes" em um único slice. \n
Importante: Este método altera o array subjacente. Após a operação, o elemento 3 fisicamente permanece na memória (será sobrescrito apenas se você adicionar novos elementos). Mas para você, ele "desapareceu" do slice.
Método 2: Remoção por índice (sem preservação da ordem) — método rápido
\n\nSe a ordem dos elementos não for importante (por exemplo, ao trabalhar com um conjunto de dados não ordenado), você pode usar o truque de "substituir pelo último":
\n\nfunc removeFast(s []int, index int) []int {\n // Substitui o elemento removido pelo último\n s[index] = s[len(s)-1]\n // Corta o slice, descartando o último elemento\n return s[:len(s)-1]\n}\n\nfunc main() {\n slice := []int{1, 2, 3, 4, 5}\n slice = removeFast(slice, 1) // remove o elemento no índice 1 (valor 2)\n fmt.Println(slice) // [1 5 3 4] — ordem alterada!\n}\n\n\nPor que é mais rápido? Porque não copiamos metade do slice. Apenas movemos um elemento (o último) para o lugar do removido e truncamos o slice. Operação O(1) contra O(n) do primeiro método.
\n\nQuando usar: Em loops intensivos, quando o desempenho é crítico e a ordem não importa (por exemplo, ao remover de um pool de objetos).
\n\nMétodo 3: Remoção por valor (primeira ocorrência)
\n\nFrequentemente é necessário encontrar e remover um elemento pelo seu valor, não pelo índice. Para isso, primeiro encontramos o índice e depois aplicamos um dos métodos acima.
\n\nfunc removeByValue(s []string, value string) []string {\n for i, v := range s {\n if v == value {\n return append(s[:i], s[i+1:]...)\n }\n }\n return s // se não encontrar, retorna o slice original