1

I have the code as below and defer wasn't executed.

Doesn't defer work if we put it after panic?

package main

import (
  "fmt"
)

func main() {
  fmt.Println("begining of main")
  panic("stop here")
  defer fmt.Println("end of main")
}

nghiatran@nghiatran-VB:~/go/src/defer$ go run main.go
begining of main
panic: stop here

goroutine 1 [running]:
main.main()
        /home/nghiatran/go/src/defer/main.go:9 +0x96
exit status 2
nghiatran@nghiatran-VB:~/go/src/defer$
Grzegorz Żur
  • 47,257
  • 14
  • 109
  • 105
NghiaTran
  • 55
  • 1
  • 4
  • 2
    You defer statement is never _reached_. Actually nothing in a function after panic is reached and non of these not-reached statements are executed. This has _nothing_ to do with defer. – Volker Sep 05 '19 at 07:46
  • 2
    Why would you expect something after the program exits to run? – Jonathan Hall Sep 05 '19 at 07:53
  • The problem is not a typographical error. It is about how defer statement work. In other languages the code after error executes. For instance catch and finally blocks. I guess OP expected this. – Grzegorz Żur Sep 07 '19 at 08:26

2 Answers2

9

The order of statements is wrong. Defer pushes function call to the stack. At the end of the function execution stacked calls are taken in reverse order and are executed. It does not matter whether function panics or not.

You need to push the function call first and then panic.

package main

import (
  "fmt"
)

func main() {
   defer fmt.Println("end of main") // push the call to the stack
   fmt.Println("begining of main")
   panic("stop here")
   // the deffered functions are called as if they where here
}

The defer statement works differently than catch and finally blocks but it offer the same functionality.

See Use of defer in Go

Grzegorz Żur
  • 47,257
  • 14
  • 109
  • 105
4

defer won't work after panic because the control never reached the statement, hence it was never registered. This is like printing something after a return statement in a function, it's basically an unreachable code.