Rules for the use of defer

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

In Golang, the defer code block adds a function call to the function call list. This function call is not a normal function call, but instead adds a function call after the function returns, that is, return. Therefore, defer is often used to release function internal variables.

In order to learn the defer behavior better, let's first look at the following code:

func CopyFile(dstName, srcName string) (written int64, err error) {  src, err := os.Open(srcName)  if err != nil {  return  }dst, err := os.Create(dstName)  if err != nil {  return  }written, err = io.Copy(dst, src)  dst.Close()  src.Close()  return  }

This code can run, but there is a ' security risk '. If DST is called, err: = OS. Create (DstName) fails, the function executes a return exit run. However, the SRC (file handle) that was created previously was not released. The above code is simple, so we can see that there is a problem with the file not being released. If our logic is complex or the code is called too much, such errors may not be discovered in time. Using defer can prevent this from happening, and here's the code that uses defer:

func CopyFile(dstName, srcName string) (written int64, err error) {  src, err := os.Open(srcName)  if err != nil {  return  }defer src.Close()dst, err := os.Create(dstName)  if err != nil {  return  }defer dst.Close()return io.Copy(dst, src)  }

With defer, we can gracefully close/clean the variables used in the code. Defer, as a feature of Golang cleanup variables, has its own unique and unambiguous behavior. The following are defer three usage rules.

Rule one when defer is declared, its parameters are parsed in real time

We use the following code to interpret this rule:

func a() {  i := 0  defer fmt.Println(i)  i++  return  }

As we said above, the defer function is called after return. So when this function is finished, is it not supposed to output 1?

The reader compiles its own look, the result output is 0. Why

This is because, although we define a function with a variable after defer: FMT. Println (i). But this variable (i) has determined its value when defer is declared. In other words, the above code is equivalent to the following code:

func a() {  i := 0  defer fmt.Println(0) //因为i=0,所以此时就明确告诉golang在程序退出时,执行输出0的操作  i++  return  }

To clarify this issue more clearly, we continue to define a defer:

func a() {  i := 0  defer fmt.Println(i) //输出0,因为i此时就是0  i++  defer fmt.Println(i) //输出1,因为i此时就是1  return  }

By running the result, you can see the value of the defer output, which is the value at the time of definition. Instead of defer the value of the variable when it is actually executed (it is important that it is not clear that it results from the expected inconsistency)

But why is the output 1 first, in the output 0? Look at the following rule two.

Rule two defer execution order for advanced back-out

When multiple defer code blocks are defined at the same time, the Golang installation is defined in the order in which they are executed , calling defer in turn. Don't say why, that's what Golang defines. We use the following code to deepen our memory and understanding:

func b() {  for i := 0; i < 4; i++ {  defer fmt.Print(i)  }}

In the loop, four defer code blocks are defined in turn. With rule one, we can tell exactly what value each defer code block should output. After installing the advanced principle, we can see that the output is 3210 in turn.

Rule three defer can read a well-known return value

Let's look at the following code:

func c() (i int) {  defer func() { i++ }()  return 1  }

The output result is 12. At the beginning, we said that defer was executed after the return call. It is important to be clear that the scope of the defer code block is still within the function, which means that the scope of the defer is still within the C function. So defer can still read the variables in the C function (if the variables inside the function cannot be read, then how to do the variable cleanup ...).

When you execute return 1, the value of I is 1. At this point, the defer code block starts executing, and I is self-increasing. So the output is 2.

Master defer above three rules of use, then when we encounter defer code block, we can clearly know the expected results of defer.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.