官术网_书友最值得收藏!

  • Go Systems Programming
  • Mihalis Tsoukalos
  • 584字
  • 2021-07-02 18:07:59

The defer keyword

The defer keyword defers the execution of a function until the surrounding function returns, and is widely used in file I/O operations. This is because it saves you from having to remember when to close an open file.

The file with the Go code that illustrates the use of defer is called defer.go and has four main parts.

The first part is the expected preamble as well as the definition of the a1() function:

package main 
 
import ( 
   "fmt" 
) 
 
func a1() { 
   for i := 0; i < 3; i++ { 
         defer fmt.Print(i, " ") 
   } 
} 

In the previous example, the defer keyword is used with a simple fmt.Print() statement.

The second part is the definition of the a2() function:

func a2() { 
   for i := 0; i < 3; i++ { 
         defer func() { fmt.Print(i, " ") }() 
   } 
} 

After the defer keyword, there is an anonymous function that is not attached to a variable, which means that after the termination of the for loop, the anonymous function will automatically disappear. The presented anonymous function takes no arguments but uses the i local variable in the fmt.Print() statement.

The next part defines the a3() function and has the following Go code:

func a3() { 
   for i := 0; i < 3; i++ { 
         defer func(n int) { fmt.Print(n, " ") }(i) 
   } 
} 

This time, the anonymous function requires an integer parameter that is named n and takes its value from the i variable.

The last part of defer.go is the implementation of the main() function:

func main() { 
   a1() 
   fmt.Println() 
   a2() 
   fmt.Println() 
   a3() 
   fmt.Println() 
} 

Executing defer.go will print the following, which might surprise you at first:

$ go run defer.go
2 1 0
3 3 3
2 1 0

So, now it is time to explain the output of defer.go by examining the way a1(), a2(), and a3() execute their code. The first line of output verifies that deferred functions are executed in Last In First Out (LIFO) order after the return of the surrounding function. The for loop in a1() defers a single function call that uses the current value of the i variable. As a result, all numbers are printed in reverse order because the last used value of i is 2. The a2() function is a tricky one because due to defer, the function body is evaluated after the for loop ends while it is still referencing the local i variable, which at that time was equal to 3 for all evaluations of the body. As a result, a2() prints the number 3 three times. Put simply, you have three function calls that use the last value of a variable because this is what is passed to the function. However, this is not the case with the a3() function because the current value of i is passed as an argument to the deferred function, due to the (i) code at the end of the a3() function definition. So, each time the deferred function is executed, it has a different i value to process.

As using defer can be complicated, you should write your own examples and try to guess their output before executing the actual Go code to make sure that your program behaves as expected. Try to be able to tell when the function arguments are evaluated and when the function body is actually executed.

You will see the defer keyword in action again in Chapter 6, File Input and Output.

主站蜘蛛池模板: 滁州市| 龙州县| 北海市| 通道| 台中县| 报价| 三台县| 峡江县| 拜泉县| 察隅县| 大庆市| 花莲市| 河池市| 永清县| 沁源县| 天祝| 会泽县| 霍林郭勒市| 萨迦县| 平乡县| 尤溪县| 普安县| 绥阳县| 尉犁县| 牡丹江市| 镇雄县| 西畴县| 加查县| 手机| 于都县| 东源县| 淮阳县| 胶州市| 马鞍山市| 忻州市| 尼勒克县| 墨脱县| 兴国县| 上杭县| 姜堰市| 阳信县|