Garantindo a execução de funções em Go com defer

A linguagem Go carrega nativamente várias ideias/ferramentas focadas em desempenho e simplificação de código. Uma função nativa que merece destaque é o defer, a ideia por trás do defer é muito simples:

Processar a função parametrizada no fim da execução do bloco em que ele é invocado.

Isso quer dizer o seguinte, no trecho de código abaixo o f.Close()será executado independentemente de qual return encerre a função.

func create_file() (string, error) {
f, err := os.Create("/tmp/go_sample")
defer f.Close()
if err != nil {
return "", err
}
return f.Name(), nil
}

Dessa forma o defer previne maus usos de memória uma vez que ponteiros para arquivos ou conexões com serviços externos são encerrados independentemente do fluxo que aplicação siga. Para isso é importante sempre adicionar um defer com a finalização de uso desses recursos imediatamente após sua inicialização.

No que diz respeito aos fluxos da aplicação, o uso do defer é tão garantido que mesmo que a aplicação seja encerrada com erro por conta da ocorrência de um Run-time Panic:

func main() {
defer fmt.Println("Successful print")
panic("unrecoverable error")
}

Por fim, um ponto de atenção ao utilizar o defer é em relação aos parâmetros das funções que se deseja postergar, isso porque os valores desses parâmetros são carregados no momento em que a função defer é invocada:

func main() {
val := 0
defer fmt.Println(val)
val = 10
}

Neste caso o programa irá imprimir o valor 0 que corresponde ao valor da variável val no momento em que o defer foi invocado.