Esse post faz parte de uma série onde pretendo compartilhar o básico essencial para desenvolver com GoLang.
As comparações lógicas utilizando os operadores ==
ou !=
não tem muito mistério. Ou seu código compara se os valores são iguais ou diferentes.
Mas existem alguns detalhes importantes de saber sobre o que você está comparando.
Interface Comparable
A primeira coisa é saber o que pode ser comparado com esses operadores, o lugar mais óbvio para saber disso é a documentação do Go: seção sobre comparadores
E outra opção é olhar a interface comparable, que foi adicionada junto com a implementação de generics do Go, todos os tipos que implementam essa interface são comparáveis.
Então basicamente todos os tipos primitivos definidos pelo Go são comparáveis, como: string
, números
(int
, float
, complex
), bool
.
Comparação de tipos complexos
Alguns tipos possuem condições para serem ou não comparáveis. Que é o caso de: struct
, slices
e channels
.
Somente são comparáveis se os elementos deles também o forem.
O interessante é que o Go valida isso a nível de compilação, te ajudando a evitar erros em runtime, por exemplo:
//Esse código compila e a comparação funciona: func main() { test1 := struct { name string }{} test2 := struct { name string }{} if test1 == test2 { fmt.Println("Funciona") } }
No código acima estou criando dois structs com o atributos equivalentes e a comparação funciona.
//Esse código não compila func main() { test1 := struct { name string attributes map[string]string }{} test2 := struct { name string attributes map[string]string }{} if test1 == test2 { fmt.Println("Cade?") } }
Já esse código vai falhar na compilação com o erro invalid operation
.
Isso acontece porque map
não é um tipo comparável em Go.
Detalhes sobre structs e map
É bastante conveniente poder comparar structs com ==
, já que esse são os tipos onde customizamos nossas modelagens.
Mas mesmo quando estiver utilizando um tipo não comparável há algumas maneiras de simplificar o código, e saber disso vai te poupar de escrever condições bem chatas.
Bom vamos imaginar que estamos trabalhando no sistema de uma escola e temos a seguinte struct não comparável:
type student struct { ID int name string age int course string attributes map[string]string }
A parte boa, esse struct possui um campo ID, o que facilita muito se você estiver trabalhando com dados persistidos.
Agora imagina só se estiver trabalhando com dados ainda transientes, por exemplo se estiver lendo um arquivo e precisar fazer algum tipo de processamento antes de persistir esses dados.
Você sempre vai ter a opção de comparar campo a campo, não é nada conveniente, mas funciona. Mas você pode fazer uso de composição de struct da seguinte forma:
func main() { type identity struct { name string age int course string } type student struct { ID int identity attributes map[string]string } s1 := student{ identity: identity{ name: "Chuck", age: 10, course: "golang", }, attributes: map[string]string{ "last_score": "10", }, } s2 := student{ identity: identity{ name: "Chuck", age: 10, course: "golang", }, attributes: map[string]string{ "last_score": "20", }, } s3 := student{ identity: identity{ name: "Chuck", age: 12, course: "golang", }, attributes: map[string]string{ "last_score": "20", }, } if s1.identity == s2.identity { fmt.Println("Achou", s1) } if s1.identity != s3.identity { fmt.Println("Não achou") } }
A alternativa a esse código seria fazer condições como essas:
if s1.name == s2.name && s1.age == s2.age && s1.course == s2.course { fmt.Println("Achou", s1) }
Você poderia extrair para uma função, para ficar menos confuso, mas mesmo assim teria que ficar mantendo essas comparações.
Faça bom uso de composição isso pode simplificar bastante o seu código!
Resumo
- Conheça a interface
comparable
- Tipos primitivos são comparáveis
- Tipos complexos podem ou não ser comparáveis
- Use a composição a seu favor.
Top comments (0)