The use of defer in Go is summarized

  • 2020-06-03 06:45:16
  • OfStack

preface

defer is a keyword in the golang language that is used to free resources and is called before the function returns.

1 The following model is generally adopted:


f,err := os.Open(filename)
if err != nil {
  panic(err)
}
defer f.Close()

If there are multiple defer expressions, the call order is similar to the stack, and the later the defer expression is called first.

The syntax of the delayed call function is as follows:


defer func_name(param-list)

When a function is called with the key defer, the execution of the function is delayed until the function containing the defer statement is about to return. For example:


func main() {
  defer fmt.Println("Fourth")
  fmt.Println("First")
  fmt.Println("Third")
}

The final printing order is as follows:


First
Second
Third

Note that the value of the function argument called by defer is determined when defer is defined.

Such as:


i := 1
defer fmt.Println("Deferred print:", i)
i++
fmt.Println("Normal print:", i)

The print reads as follows:


Normal print: 2
Deferred print: 1

So we know that in the "defer fmt.Println("Deferred print:", i)" At the time of the call, the value of i is already determined and therefore equivalent to defer fmt.Println("Deferred print:", 1) .

It is important to note that the value of the function argument called by defer is determined at the time of defer definition, while the value of the variable used within the defer function is determined at the time the function runs.

Such as:


func f1() (r int) {
  r = 1
  defer func() {
    r++
    fmt.Println(r)
  }()
  r = 2
  return
}

func main() {
  f1()
}

In the above example, the final print is "3" because the defer function is executed after the assignment of "r = 2", so within this function, the value of r is 2 and increases to 3.

defer order

If there are multiple defer calls, the order of the calls is in first and out last, similar to push and push 1:


func main() {
  defer fmt.Println(1)
  defer fmt.Println(2)
  defer fmt.Println(3)
  defer fmt.Println(4)
}

The first one to be executed "fmt.Println(4)" And then the "fmt.Println(3)" The final output is as follows:


4
3
2
1

Pay attention to the main points

The defer function call is executed after the outer function has set the return value, and before it is about to return.

Such as:


func f1() (r int) {
  defer func() {
    r++
  }()
  return 0
}
func main() {
  fmt.Println(f1())
}

The above fmt.Println(f1()) What is it printing? #63; Many friends may think that it prints 0, but the correct answer is 1.

To understand this, we need to keep two things in mind

1. The defer function call is executed after the outer function has set the return value, and before the return value is about to be returned

The return XXX operation is not atomic.

Let's rewrite 1 of the above example to make it clear:


defer func_name(param-list)
0

The defer function is called after the assignment "r = 0" and the return statement is the last.

Therefore, the above code is equivalent to:


defer func_name(param-list)
1

Let's look at a more interesting example:


defer func_name(param-list)
2

If we understand what is said above, then the triple function is easy to understand, which is actually:


func triple(x int) (r int) {
  r = double(x)
  func() {
    r += x
  }()
  return
}

defer expression usage scenario

defer is usually used in pairs of open/close, connect/disconnect, lock/unlock and so on to ensure that resources are properly released in all circumstances. In this sense, the defer operation and try in Java... The finally block works in a similar way.

Such as:


defer func_name(param-list)
4

in increment Function, we in order to avoid the occurrence of race conditions, and using the Mutex lock. In concurrent programming, lock live to forget (or some cases unlock is not executed), tend to have disastrous consequences. In order to in any case, are intended to ensure that after the lock operation, all corresponding unlock operation, we can use defer call unlock operation.

conclusion

The above is the full content of this article, I hope to bring you a certain help in your study or work. If you have any questions, you can leave a message.


Related articles: