Skip to content

Instantly share code, notes, and snippets.

@go101
Last active November 12, 2019 15:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save go101/45b1e6e0933385fc467b4841276c34c4 to your computer and use it in GitHub Desktop.
Save go101/45b1e6e0933385fc467b4841276c34c4 to your computer and use it in GitHub Desktop.
All kinds of Panic/recover/Goexit cases

A good panic/reover/Goexit explaination should cover these following cases.

  1. The program exits normally.
package main

func main() {
	defer func() {
		recover() // recover "bye"
	}()

	panic("bye")
}
  1. The program exits normally. Panic 2 shadows panic 1, then shadows panic 0.
package main

import "fmt"

func main() {
	defer func() {
		fmt.Print(recover())
	}()
	
	defer func() {
		defer panic(2)
		func () {
			panic(1)
		}()
	}()
	panic(0)
}
  1. The program crashes for panicking.
package main

func main() {
	defer func() {
		defer func() {
			recover() // no-op
		}()
	}()
	defer func() {
		func() {
			recover() // no-op
		}()
	}()
	func() {
		defer func() {
			recover() // no-op
		}()
	}()
	func() {
		defer recover() // no-op
	}()
	func() {
		recover() // no-op
	}()
	recover()       // no-op
	defer recover() // no-op
	panic("bye")
}
  1. The second recover call (by line number) is a no-op.
package main

func demo() {
	defer func() {
		defer func() {
			recover() // this one recovers panic 2
		}()

		defer recover() // no-op

		panic(2)
	}()
	panic(1)
}

func main() {
	demo()
}
  1. The program should exit quickly.
package main

import "runtime"

func f() {
	defer func() {
		recover()
	}()
	defer panic("bye")
	runtime.Goexit()
}

func main() {
	c := make(chan struct{})
	go func() {
		defer close(c)
		f()
		for {
			runtime.Gosched()
		}
	}()
	<-c
}
  1. The program should exit for panicking?
package main

import "runtime"

func main() {
	c := make(chan struct{})
	go func() {
		defer close(c)
		defer runtime.Goexit()
		panic("bye")
	}()
	<-c
}
  1. The program should exit normally?
package main

import (
	"fmt"
	"runtime"
)

func main() {
	defer func() {
		fmt.Print(recover())
	}()
	
	defer runtime.Goexit()

	panic(0)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment