defer, panic, e recover
defer agenda uma chamada de function para rodar bem antes da function ao redor retornar, não importa como ela retorne. É usado com mais frequência para limpeza — fechar um arquivo, destravar um mutex — escrito bem ao lado do código que o abriu.
package main
import "fmt"
func main() {
fmt.Println("start")
defer fmt.Println("cleanup")
fmt.Println("end")
}start end cleanup
panic e recover
panic para imediatamente a execução normal e começa a desenrolar a call stack — o equivalente mais próximo do Go a lançar uma exception, reservado para situações verdadeiramente excepcionais, não para tratamento de erros do dia a dia. recover, chamado dentro de uma function diferida, para esse desenrolamento e deixa o programa continuar, e é assim que safeDivide abaixo transforma um panic em tempo de execução (dividir por zero) em um valor de retorno comum.
package main
import "fmt"
func safeDivide(a, b int) (result int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("recovered from:", r)
result = 0
}
}()
return a / b
}
func main() {
fmt.Println(safeDivide(10, 2))
fmt.Println(safeDivide(10, 0))
}5 recovered from: runtime error: integer divide by zero 0
A seguir: closures — functions que capturam variáveis do escopo ao redor delas.
Practice exercise
Use defer para imprimir "goodbye" depois de imprimir "hello" (defer deve fazer "goodbye" imprimir por último, mesmo aparecendo primeiro no código).