Comparação de struct, slice e map em Go: do iniciante ao profissional
\n\nVocê já escreveu código em Go que precisava comparar duas structs, dois slices ou dois maps e recebeu um erro de compilação: invalid operation: cannot compare? Se sim — você não está sozinho. Esta é uma das perguntas mais populares no Stack Overflow (dezenas de milhares de visualizações!), que deixa até desenvolvedores experientes, vindos de outras linguagens, confusos.
Neste artigo, vamos entender de uma vez por todas como comparar corretamente tipos de dados compostos em Go. Você aprenderá por que == nem sempre funciona, quando usar reflect.DeepEqual e como escrever sua própria função de comparação eficiente. Vamos lá!
Por que a comparação simples com == nem sempre funciona?
\n\nEm Go, o operador == funciona apenas para tipos comparáveis (comparable). Eles incluem:
- \n
- Tipos básicos:
int,string,bool,float, etc. \n - Ponteiros (
pointer) \n - Canais (
channel) \n - Interfaces (se os tipos dinâmicos forem comparáveis) \n
- Structs, cujos todos os campos são comparáveis \n
- Arrays (
array), se o elemento do array for comparável \n
Já slices e maps — não são comparáveis diretamente com ==. Tentar fazer isso resultará em um erro de compilação. Por quê? Porque slice é um tipo de referência que inclui um ponteiro para os dados, comprimento e capacidade. Dois slices podem ser "iguais" em conteúdo, mas ter estruturas internas diferentes.
package main\n\nimport "fmt"\n\nfunc main() {\n a := []int{1, 2, 3}\n b := []int{1, 2, 3}\n \n // Erro de compilação!\n // fmt.Println(a == b) \n \n fmt.Println("Funciona apenas com nil:")\n fmt.Println(a == nil) // false\n fmt.Println(b == nil) // false\n}\n\nO mesmo se aplica a maps. A única coisa que você pode verificar com == é a igualdade com nil.
Comparação de structs em Go
\n\nA comparação de structs é o caso mais traiçoeiro. Se todos os campos da sua struct forem tipos comparáveis, então == funciona!
type Person struct {\n Name string\n Age int\n}\n\nfunc main() {\n p1 := Person{"Alice", 30}\n p2 := Person{"Alice", 30}\n \n fmt.Println(p1 == p2) // true — funciona!\n}\n\nMas o problema surge quando a struct contém um slice ou map:
\n\ntype PersonWithHobbies struct {\n Name string\n Age int\n Hobbies []string // slice — tipo não comparável\n}\n\nfunc main() {\n p1 := PersonWithHobbies{"Bob", 25, []string{"reading", "coding"}}\n p2 := PersonWithHobbies{"Bob", 25, []string{"reading", "coding"}}\n \n // Erro de compilação!\n // fmt.Println(p1 == p2)\n}\n\nNeste caso, o compilador Go emitirá um erro: struct containing []string cannot be compared.
Solução nº1: reflect.DeepEqual — universal, mas lento
\n\nA maneira mais simples de comparar qualquer tipo complexo é usar a função reflect.DeepEqual da biblioteca padrão do Go. Ela percorre recursivamente structs, slices, maps e compara seu conteúdo.
import (\n "fmt"\n "reflect"\n)\n\nfunc main() {\n // Comparação de slices\n a := []int{1, 2, 3}\n b := []int{1, 2, 3}\n fmt.Println(reflect.DeepEqual(a, b)) // true\n \n // Comparação de maps\n m1 := map[string]int{"a": 1, "b": 2}\n m2 := map[string]int{"a": 1, "b": 2}\n fmt.Println(reflect.DeepEqual(m1, m2)) // true\n \n // Comparação de structs com campos não comparáveis\n p1 := PersonWithHobbies{"Bob", 25, []string{"reading"}}\n p2 := PersonWithHobbies{"Bob", 25, []string{"reading"}}\n fmt.Println(reflect.DeepEqual(p1, p2)) // true\n}\n\n<