


Use eight demos to understand the five major features of Go language defer
Apr 23, 2023 pm 05:40 PMUsing the defer
keyword in Go language can delay code execution until the end of the function. In development, we often use the defer
keyword to complete the aftermath work, such as closing open file descriptors, closing connections, and releasing resources.
func?demo0()?{ ????fileName?:=?"./test.txt" ????f,?_?:=?os.OpenFile(fileName,?os.O_RDONLY,?0) ????defer?f.Close() ????contents,?_?:=?ioutil.ReadAll(f) ????fmt.Println(string(contents))}
defer
The keyword usually follows immediately after the resource opening code to prevent subsequent forgetting to release the resource. The code declared by defer will not actually be executed until the end of the function. Although defer is simple and easy to use, but if you ignore its features, you will face confusion during development . Therefore, I summarized the five major features of defer and gradually introduced the features of defer through 8 demos.
Feature 1: Calling order when multiple defers are used: first in, last out
When multiple defer keywords are used, the defer statement declared first is called later. Similar to the "stack" first-in-last-out feature, this feature of defer is also easy to understand. Resources opened by first may be relied upon by subsequent code, so ## It is safe to release after #.
func?demo1()?{ ????for?i?:=?0;?i?<?5;?i++?{ ????????defer?fmt.Println("defer:",?i) ????}}//?defer:?4//?defer:?3//?defer:?2//?defer:?1//?defer:?0Feature 2: The scope is the current function, and there are different defer stacks under different functionsRun demo2. It can be seen from the results that the first anonymous function and the second anonymous function The order of defer execution of functions does not matter.
The defer scope is only the current function and is executed at the end of the current function, so there are different defer stacks under different functions.
func?demo2()?{ ????func()?{ ????????defer?fmt.Println(1) ????????defer?fmt.Println(2) ????}() ????fmt.Println("===?新生代農(nóng)民工啊?===") ????func()?{ ????????defer?fmt.Println("a") ????????defer?fmt.Println("b") ????}()}//?2//?1//?===?新生代農(nóng)民工啊?===//?b//?a
Feature 3: Function parameters after defer are confirmed at the time of declaration (precalculated parameters)
Run demo3_1, according to the results, we can conclude: defer inThe value of the formal parameter n has been confirmed when is declared, not when is executed; therefore, no matter how the subsequent variable num changes, it will not affect the output result of defer.
func?demo3_1()?{ ????num?:=?0 ????defer?func(n?int)?{ ????????fmt.Println("defer:",?n) ????}(num) ????//?等同?defer?fmt.Println("defer:",?num) ????for?i?:=?0;?i?<?10;?i++?{ ????????num++ ????} ????fmt.Println(num)}//10//defer:?0Run demo3_2, why is the final output result of defer here the same as the variable num? Because pointers are used here.
defer
When declaring, the address pointed by the formal parameter p pointer has been confirmed, pointing to the variable num; subsequently the variable num changes. So when defer is executed, the output is the current value of the variable num pointed to by the p pointer.
func?demo3_2()?{ ????num?:=?0 ????p?:=?&num????defer?func(p?*int)?{ ????????fmt.Println("defer:",?*p) ????}(p) ????for?i?:=?0;?i?<?10;?i++?{ ????????num++ ????} ????fmt.Println(*p)}//10//defer:?10Look at demo3_3 again. The variables printed by defer are not passed in through function parameters. The "global variable" num is only obtained when defer
is executed, so the output result of defer is the same as the variable. num is consistent. func?demo3_3()?{
????num?:=?0
????defer?func()?{
????????fmt.Println("defer:",?num)
????}()
????for?i?:=?0;?i?<?10;?i++?{
????????num++
????}
????fmt.Println(num)}//10//defer:?10
Feature 4: return and defer execution order: return first defer then
Run demo4_1, you can find that defer and return are executed at the end of the function, but return is executed before defer;
func?demo4_1()?(int,?error)?{ ????defer?fmt.Println("defer") ????return?fmt.Println("return")}//?return//?defer
This is obvious from the output results
, but when the execution order of return and defer and the**function return value** "meet", Many complex scenarios will result.
In demo4_2, the function uses to name the return value
, and the final output result is 7. It has gone through the following processes:
- (First) the variable num is used as the return value, and the initial value is 0;
- (Second) Then The variable num is assigned a value of 10;
- (Then) when return, the variable num is reassigned a value of 2 as the return value;
- (Finally) the variable num is used as the return value, and the final function return result is 7;
-
func?demo4_2()?(num?int)?{ ?num?=?10 ?defer?func()?{ ?????num?+=?5 ?}() ?return?2}//?7
Let’s look at another example.
anonymous return value
, and the final result output is 2. The process is as follows:
- Enters the function, and the return value variable is not created at this time;
- creates the variable num and assigns the value to 10; When
- return, create a function return value variable and assign it a value of 2; you can regard this return value variable as an anonymous variable, or as a, b, c, or d variable ..., but it is not the variable num;
- defer, no matter how you modify the variable num, it has nothing to do with the function return value;
- Therefore, the final function return result is 2;
-
func?demo4_3()?int?{ ?num?:=?10 ?defer?func()?{ ?????num?+=?5 ?}() ?return?2}//?2
Feature 5: When panic occurs, the declared defer will pop out of the stack and execute
Run demo5_1, you can see that when panic occurs, Trigger the declared defer to pop out of the stack and then panic. However, the defer declared after the panic will not be executed.
func?demo5_1()?{ ?defer?fmt.Println(1) ?defer?fmt.Println(2) ?defer?fmt.Println(3) ?panic("沒(méi)點(diǎn)贊異常")?//?觸發(fā)defer出棧執(zhí)行 ?defer?fmt.Println(4)?//?得不到執(zhí)行}
It is precisely by using this feature that panic can be captured through recover in defer to prevent the program from crashing.
func?demo5_2()?{ ?defer?func()?{ ?????if?err?:=?recover();?err?!=?nil?{ ?????????fmt.Println(err,?"問(wèn)題不大") ?????} ?}() ?panic("沒(méi)點(diǎn)贊異常")?//?觸發(fā)defer出棧執(zhí)行 ?//?...}
Attached
Full code:
github.com/newbugcoder/learngo/tre...
The above is the detailed content of Use eight demos to understand the five major features of Go language defer. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

The problem of using RedisStream to implement message queues in Go language is using Go language and Redis...

What should I do if the custom structure labels in GoLand are not displayed? When using GoLand for Go language development, many developers will encounter custom structure tags...

Queue threading problem in Go crawler Colly explores the problem of using the Colly crawler library in Go language, developers often encounter problems with threads and request queues. ?...

The difference between string printing in Go language: The difference in the effect of using Println and string() functions is in Go...

Which libraries in Go are developed by large companies or well-known open source projects? When programming in Go, developers often encounter some common needs, ...

The library used for floating-point number operation in Go language introduces how to ensure the accuracy is...

Do I need to install an Oracle client when connecting to an Oracle database using Go? When developing in Go, connecting to Oracle databases is a common requirement...

Resource management in Go programming: Mysql and Redis connect and release in learning how to correctly manage resources, especially with databases and caches...
