unexpected-go

Unexpected Golang behaviors

View on GitHub

Introduction

After finishing the Golang tutorial, one expects that this code will recover from any panic:

func main() {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println("Recovered from panic", err)
        }
    }()

    // ...
}

However it will not, if the panic value is nil:

func main() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("Recovered from panic", err)
		}
	}()

	panic(nil)
}

Workarounds

bradfitz mentions as the proper way something like this:

func main() {
	panicked := true
	defer func() {
		if err := recover(); err != nil || panicked {
			fmt.Println("Recovered from panic", err)
		}
	}()

	panic(nil)
	panicked = false
}

An alternative approach would also be to wrap your calls with some kind of function that would transform nil panics into non-nil panics:

func runWithoutNilPanics(f func()) {
    panicked := true
	defer func() {
		if err := recover(); err != nil {
		    panic(err)
		} else if panicked {
		    panic(fmt.Errorf("panicked with nil panic"))
		}
	}()

	f()
}