基本用法

  • 参数会在 defer 方法执行时,固化
  1. func a() {
  2. i := 0
  3. defer fmt.Println(i) // 0
  4. i++
  5. return
  6. }
  • 执行顺序后进先出
  1. func b() {
  2. for i := 0; i < 4; i++ {
  3. defer fmt.Print(i)
  4. }
  5. }
  6. // 3210
  • 操作返回值变量
  1. func c() (i int) {
  2. defer func() { i++ }()
  3. return 1
  4. }

调整错误返回值

  1. func Create() (err error) {
  2. defer func() {
  3. if err != nil {
  4. db.Rollback()
  5. } else {
  6. err = db.Commit()
  7. }
  8. }()
  9. }

示例:

  1. func CopyFile(dstName, srcName string) (written int64, err error) {
  2. src, err := os.Open(srcName)
  3. if err != nil {
  4. return
  5. }
  6. defer src.Close()
  7. dst, err := os.Create(dstName)
  8. if err != nil {
  9. return
  10. }
  11. defer dst.Close()
  12. return io.Copy(dst, src)
  13. }

defer 可嵌套使用

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. defer func() {
  7. defer func() {
  8. fmt.Println("Inner defer")
  9. }()
  10. fmt.Println("Outer defer")
  11. }()
  12. fmt.Println("Execution finished")
  13. }
  14. // Execution finished
  15. // Outer defer
  16. // Inner defer

配合 panic

  1. package main
  2. import "fmt"
  3. func main() {
  4. f()
  5. fmt.Println("Returned normally from f.")
  6. }
  7. func f() {
  8. defer func() {
  9. if r := recover(); r != nil {
  10. fmt.Println("Recovered in f", r)
  11. }
  12. }()
  13. fmt.Println("Calling g.")
  14. g(0)
  15. fmt.Println("Returned normally from g.")
  16. }
  17. func g(i int) {
  18. if i > 3 {
  19. fmt.Println("Panicking!")
  20. panic(fmt.Sprintf("%v", i))
  21. }
  22. defer fmt.Println("Defer in g", i)
  23. fmt.Println("Printing in g", i)
  24. g(i + 1)
  25. }
  26. // Calling g.
  27. // Printing in g 0
  28. // Printing in g 1
  29. // Printing in g 2
  30. // Printing in g 3
  31. // Panicking!
  32. // Defer in g 3
  33. // Defer in g 2
  34. // Defer in g 1
  35. // Defer in g 0
  36. // Recovered in f 4
  37. // Returned normally from f.