Vamos falar um pouco sobre genéricos em Go.
Qual é a diferença entre generics e interface vazia?
Genéricos são preferíveis porque oferecem segurança de tipo em tempo de compilação, evitam casts e panics, tornam o código mais legível e permitem melhor inferência e autocompletar. Além disso, tendem a ser mais eficientes do que soluções baseadas em type assertions/reflection. Use interface{} apenas quando realmente precisar aceitar qualquer tipo sem restrições.
Pensando nisso, veja algumas formas de implementar generics em Go:
Cenário: somar os valores de um map cujos valores podem ser float64 ou int. Podemos usar uma única função genérica.
package main
func Total[T float64 | int](a map[string]T) T {
var sum T
for _, v := range a {
sum += v
}
return sum
}
func main() {
a := map[string]float64{
"apple": 1.5,
"banana": 2.0,
"orange": 3.0,
}
b := map[string]int{
"apple": 1,
"banana": 2,
"orange": 3,
}
println(Total(a)) // Output: 6.5
println(Total(b)) // Output: 6
}Outra alternativa é usar constraints, isto é, definir uma interface com a união dos tipos permitidos.
package main
type Numbers interface {
float64 | int
}
func Total[T Numbers](a map[string]T) T {
var sum T
for _, v := range a {
sum += v
}
return sum
}
func main() {
a := map[string]float64{
"apple": 1.5,
"banana": 2.0,
"orange": 3.0,
}
b := map[string]int{
"apple": 1,
"banana": 2,
"orange": 3,
}
println(Total(a)) // Output: 6.5
println(Total(b)) // Output: 6
}Usar o ~ (til) indica “tipos com o mesmo tipo subjacente”. Então essa constraint aceita int e float64 e também tipos definidos com base neles (ex.: type MyFloat float64)
package main
type MyFloat float64
type Numbers interface {
~float64 | ~int
}
func Total[T Numbers](a map[string]T) T {
var sum T
for _, v := range a {
sum += v
}
return sum
}
func main() {
a := map[string]float64{
"apple": 1.5,
"banana": 2.0,
"orange": 3.0,
}
b := map[string]int{
"apple": 1,
"banana": 2,
"orange": 3,
}
c := map[string]MyFloat{
"apple": 1.5,
"banana": 2.0,
"orange": 3.0,
}
println(Total(a)) // Output: 6.5
println(Total(b)) // Output: 6
println(Total(c)) // Output: 6.5
}
0 comentários