Rafael

Engenheiro de Software

Olá, Eu sou Rafael. Estou construindo coisas para a web e mobile.

Um desenvolvedor dedicado a criar experiências digitais de alto desempenho, acessíveis e limpas. Eu me especializo em transformar problemas complexos em soluções de engenharia elegantes.

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.

GO
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.

GO
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)

GO
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

Deixe seu comentário