Benchmark Retornos Nomeados vs Explicitos em Go
Surgiu uma dúvida no grupo de estudos de Go sobre a diferença de velocidade entre tipos de retorno. A hipótese é que retornos nomeados são mais rápidos que retornos explícitos.
Felizmente, Go possui um bom conjunto de ferramentas, e podemos verificar essa hipótese.
Vamos começar criando um código com duas funções de soma: uma com retornos nomeados e outra com retornos explícitos.
package main
import (
"testing"
)
// Função com retornos nomeados
func somaNomeados(a, b int) (resultado int, err error) {
resultado = a + b
return
}
// Função com retornos explícitos
func somaExplicitos(a, b int) (int, error) {
return a + b, nil
}
Em seguida, criamos as funções de benchmark. O nome dessas funções é importante, pois a ferramenta de testes do Go procura funções que comecem com a palavra Benchmark.
func BenchmarkSomaNomeados(b *testing.B) {
for i := 0; i < b.N; i++ {
somaNomeados(1, 2)
}
}
func BenchmarkSomaExplicitos(b *testing.B) {
for i := 0; i < b.N; i++ {
somaExplicitos(1, 2)
}
}
Nomeie o arquivo como benchmark_retornos_test.go
. Além do nome das funções, o nome do arquivo é importante. Ele deve terminar com _test.go
para que o Go encontre os testes.
Para rodar o benchmark, execute o seguinte comando:
go test -bench=.
No meu caso, o resultado foi este:
goos: darwin
goarch: arm64
pkg: benchmarkRetorno
cpu: Apple M2
BenchmarkSomaNomeados-8 1000000000 0.2926 ns/op
BenchmarkSomaExplicitos-8 1000000000 0.2879 ns/op
PASS
ok benchmarkRetorno 1.167s
Para minha surpresa, os retornos explícitos foram ligeiramente mais rápidos em vários testes. Contudo, isso é provavelmente uma anomalia do teste causada pela instrumentação do Go. Diferenças de sub-nanosegundos podem ser ignoradas.
Quando compilado com go build
, o código binário gerado pelas duas funções é idêntico.
Para concluir, retornos nomeados e explícitos têm o mesmo desempenho. A escolha entre eles deve ser feita com base na legibilidade do código.