liveBook · Manning

Defer

As explained in Go in Practice, Second Edition

A deferred function is a function call scheduled by Go to execute when its surrounding function returns, including during panic unwinding.

Use `defer` to schedule a function call for when its surrounding function returns. The call runs after a return statement, at the end of the function, or during panic unwinding. Put cleanup immediately after successfully acquiring a resource so later work cannot leave it open. section 4.3.3 section 1.2.2

Close an HTTP response body

After `http.Get` succeeds, write `defer resp.Body.Close()` before reading with `io.ReadAll(resp.Body)`. The body is closed when `main` returns, including if later work panics. section 1.2.2

A deferred closure can also inspect a panic: `defer func() { if err := recover(); err != nil { fmt.Println(err) } }()`. The trailing `()` marks the function call to defer; it does not execute the body immediately. `recover` retrieves the panic value and stops further stack unwinding. section 4.3.4

Two practical boundaries matter:

  • A closure can read a variable declared before the `defer` statement, including a value assigned later. A variable declared afterward is not in scope there. section 4.3.4
  • `log.Fatal*` calls `os.Exit`, so deferred calls do not run. `log.Panicln` permits panic unwinding and deferred cleanup. section 7.2.1
Listing 7.7 Network log client
package main

import (
     "log"
     "net"
)

func main() {
     conn, err := net.Dial("tcp", "localhost:1902")    #1
     if err != nil {
            panic("Failed to connect to localhost:1902")
     }
     defer conn.Close()                            #2
     f := log.Ldate | log.Lshortfile                #3
     logger := log.New(conn, "example ", f)         #4
     logger.Println("This is a regular message.")
     logger.Panicln("This is a panic.")       #5
}

The network log client defers `conn.Close()` after connecting, then logs through that connection and triggers a panic with `logger.Panicln`. Closing during unwinding helps flush buffered log messages. section 7.2.1

How Go in Practice, Second Edition covers it

How deep it goes
Explains execution on return or panic, closure scope, recovery mechanics, and the `os.Exit` exception without detailing runtime implementation.
Examples
Uses an HTTP response body, printed execution order, a recovering closure, closure-scope examples, and a network log client.
What it assumes
Assumes basic Go functions and error handling; introduces deferred functions and briefly clarifies deferred closures.
What you can do after
Practice/perform deferred resource cleanup and panic recovery while avoiding `log.Fatal*` when cleanup must run.
How it connects
Connects resource cleanup and closures with panic recovery, `recover`, network logging, and `os.Exit`.

Also explained in

Compare how 3 books explain defer →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Practice, Second Edition. The section links point to the parts of the book it draws on.