Defer

Il comando defer registra una funzione che viene eseguita al termine della goroutine corrente o del main.

Se sono registrate più funzioni in defer, esse vengono eseguite in ordine inverso di registrazione.

Le funzioni in defer sono sempre eseguite, anche in caso di panic.

(420defer.go):

package main

import "fmt"
import "os"

func main() {

	// Crea un file
	f := createFile("/tmp/defer.txt")
	// Deferisce la chiusura al termine della funzione main
	defer closeFile(f)
	// Scrive il file
	writeFile(f)
}

func createFile(p string) *os.File {
	fmt.Println("creating")
	f, err := os.Create(p)
	if err != nil {
		panic(err)
	}
	return f
}

func writeFile(f *os.File) {
	fmt.Println("writing")
	fmt.Fprintln(f, "data")

}

func closeFile(f *os.File) {
	fmt.Println("closing")
	f.Close()
}

E' buona norma, quando si ottiene una risorsa (file descriptor, connessione a database o rete, ecc), registrare subito in defer la funzione che rilascia la risorsa. Questo è particolarmente importante nel caso di goroutine. Se una goroutine termina e non rilascia una risorsa, le altre routine attive e il main potrebbero non essere più in grado di accedere a tale risorsa.