Chapter 12 - Recovering from Failure

Exercise 1: defer

We need to be sure our Camp function calls the Fire value’s Extinguish method before the program exits. But right now, Camp is returning early due to an error, before Extinguish can be called.

We don’t want to leave a lit Fire unattended in the forest! Revise the Camp function so that Extinguish is always called, even if Camp returns early.

Solution

package main

import "fmt"

type Fire struct {
	lit bool
}

func (f Fire) Light() {
	f.lit = true
	fmt.Println("Fire lit:", f.lit)
}
func (f Fire) Extinguish() {
	f.lit = false
	fmt.Println("Fire lit:", f.lit)
}

func Camp() error {
	var fire Fire
	fire.Light()
	// All you have to do is defer a call to Extinguish
	// right after you make a call to Light! Extinguish
	// will be called when Camp exits, whether Camp does
	// so normally or due to an error.
	defer fire.Extinguish()
	return fmt.Errorf("spotted a bear")
	fmt.Println("Toasting marshmallows")
	return nil
}

func main() {
	err := Camp()
	if err != nil {
		fmt.Println("Error:", err)
	}
}

Output:

Fire lit: true
Fire lit: false
Error: spotted a bear