Preview the content

  • What does Defer do?
  • What is the execution order of multiple Deferred?
  • What is the order of execution between defer, return, and the returned value?

The role of defer

In GO, defer is a delay function that is typically used to release resources or wrap up work.

Since defer is deferred and the action is executed after the function return, it works best as a resource release.

  • Typical examples: releasing locks, closing files, closing links, etc
/ / releases the lock
func getValue(a) {
  s.Lock()
  defer s.Unlock()
  ...
}
​
// Close the file
func read(a) {
  f, err := os.OpenFile("filename", os.O_RDWR, os.ModePerm)
  defer f.Close()
  ...
}
​
// Close the link
func connect(a) {
  resp, err := grequests.Get(s.cfg.GateApiCrossMarginUrl, nil)
  defer resp.Close()
  ...
}
​
As defer is also a function, you can do a lot of closing work
func closeConnection(a){...defer func(a) {
    file.close(a)close(readChan)
  }
  ...
}
Copy the code
func sendChan(a) {
  // Capture panic to recover to prevent program crash
  defer func(a) {
    if ok := recover(a); ok ! =nil {
        fmt.Println("recover")}} ()// Send data to a chan that has been closed. This will cause a panic
  dataChan <- "message". }Copy the code
// Close the file
func read(a) error {
  f1, err := os.OpenFile("filename", os.O_RDWR, os.ModePerm)
  iferr ! =nil {
    return err
  }
  // As the defer has not been executed yet, it has returned early, and as the invalid defer has caused a memory leak
  defer f1.Close()
  
  // Correct usage, followed by resource usage statements
  f2, err := os.OpenFile("filename", os.O_RDWR, os.ModePerm)
  defer f2.Close()
  iferr ! =nil {
    return err
  }
}
Copy the code
func deferFunc1(i int) (t int) {
  t = i
  defer func(a) {
    t += 1} ()return t
}
​
func deferFunc2(i int) int {
  t := i
  defer func(a) {
    t += 1} ()return t
}
​
func deferFunc3(i int) (t int) {
  defer func(a) {
    t += i
  }()
  return 1
}
​
func deferFunc4(a) (t int) {
  defer func(i int) {
    fmt.Println(i)
    fmt.Println(t)
  }(t)
  t = 0
  return 1
}
​
func ExecDeferFunc(a) {
  // Guess the following output and order
  fmt.Println(deferFunc1(1)) 
  fmt.Println(deferFunc2(1))
  fmt.Println(deferFunc3(1))
  deferFunc4()
}
Copy the code
  • Defer is used for resource release and end work
  • The multiple invocation of defer is in LIFO order, and anything following defer can be understood as a push on the stack
  • Execute as follows: return first, return value second, and defer last. Defer modifies the final return value of the function.

Review the content

So let’s go back and look at the “actual result: 2,1,2,0,1.”

In particular, if a function returns a value, return writes the result to the returned value, as — as — return executes first, then return stores the result to the returned value, and as — as — defer

Again * * defer is delay function and action in return after * *, defer rather then press to perform an action into the stack, the more the more behind the defer to perform first, execution order is LIFO (LIFO).

Start the text!

Where the estimation is ambiguous is in the relationship between the return value and the return value, as well as in the timing of defer

It could be: 2,2,1,0,0 or 2,2,1,1,1?

Do not look at the following introduction to do the following title, here first skip the introduction of defer call order, take a look at the following more typical judgment of the defer order, can you see how many?

Call order of defer

The resource release action must follow the resource use (open, connect) statement, otherwise the defer may not be executed, resulting in a memory leak

Release the resource “Defer Guide”

  • The other function is to catch panic, which is also typical in Defer