This is a creation in Article, where the information may have evolved or changed. Welcome to the 29th chapter of [Golang Series Tutorial] (HTTPS://STUDYGOLANG.COM/SUBJECT/2). # # What is defer? The purpose of the ' defer ' statement is: A function containing the ' defer ' statement, which invokes another function before the function is going to return. This definition may seem complicated, and we can easily understand it through an example. # # example ' Gopackage mainimport ("FMT") Func finished () {FMT. Println ("finished finding largest")}func largest (nums []int) {defer finished () FMT. Println ("Started finding largest") Max: = Nums[0]for _, V: = range Nums {if v > max {max = v}}fmt. PRINTLN ("Largest number in", Nums, "was", Max)}func main () {nums: = []int{78, 109, 2, 563, 300}largest (Nums)} "[In Playgro Run on und] (Https://play.golang.org/p/IlccOsuSUE) The program above is simple enough to find the maximum value of a given slice. The ' largest ' function receives an int type of [slice] (https://studygolang.com/articles/12121) as a parameter, and then prints out the maximum value in the slice. The statement for the first line of the ' largest ' function is ' defer finished () '. This means that the ' finished () ' function is called before the ' finished () ' function is going to return. Run the program and you will see the following output: "' Started finding largest largest number in [2 109 563] is 563 finished finding largest" ' larges When the T ' function starts executing, the above two lines of output are printed. And just when ' largest ' is going to return, we call our delay function (Deferred functions) and print out ' finished FThe text of Inding largest '. :) # # Delay method ' defer ' is not limited to the invocation of [function] (https://studygolang.com/articles/11892), and calling [method] (https://studygolang.com/articles/12264) is also legal. Let's write a small program to test it. ' Gopackage mainimport ("FMT") type person struct {firstName stringlastname string}func (P-person) FullName () {fmt. Printf ("%s%s", P.firstname,p.lastname)}func main () {p: = person {firstName: "John", LastName: "Smith",}defer p.fullname ( ) FMT. Printf ("Welcome")} "[Run on Playground] (Https://play.golang.org/p/lZ74OAwnRD) in the above example, we deferred a method call on line 22nd. The other code is straightforward and is no longer explained here. The program output: ' Welcome John Smith ' # # argument value (Arguments Evaluation) in the Go language, not when the delay function is called to determine the argument, but when the execution of the ' defer ' statement, The arguments to the deferred function are evaluated. It can be understood by an example. "' Gopackage mainimport (" FMT ") func PrintA (a int) {FMT. Println ("Value of a in deferred function", a)}func main () {a: = 5defer PrintA (a) a = 10fmt. Println ("Value of a before deferred function call", a)} ' [Run on Playground] (HTTPS://PLAY.GOLANG.ORG/P/SBNWRUGOBD) In line 11th of the above program, the initial value of ' a ' is 5. When the ' defer ' statement is executed on line 12th, because ' a ' equals 5, the arguments for the delay function ' PrintA ' are alsoin 5. Then we change the value of ' a ' to 10 in line 13th. The next line prints the value of ' a '. The program outputs: "' value of a before deferred function call ten value of a in deferred function 5 ' ' from the above output, as we can see, after invoking the ' defer ' statement, though Then we change ' a ' to 10, but after calling the delay function ' PrintA (a) ', the print is still 5. # # Defer stack when you call ' defer ' multiple times within a function, Go puts the ' defer ' call into a stack and then executes it in the order of last-in first-out, LIFO. Below we write a small program that uses the ' defer ' stack to print a string in reverse order. "' Gopackage mainimport (" FMT ") func main () {name: =" Naveen "FMT. Printf ("orignal string:%s\n", String (name)) FMT. Printf ("Reversed String:") for _, V: = range []rune (name) {defer FMT. Printf ("%c", V)} "" [Run on Playground] (HTTPS://PLAY.GOLANG.ORG/P/HDK623OZUW) in the above program in line 11th, the ' for Range ' loop will traverse a string and 12 lines call the ' defer FMT. Printf ("%c", V) '. These deferred calls are added to a stack and executed in LIFO order, so the string is printed in reverse. The program will output: ' ' orignal string:naveen reversed String:neevan ' # # # defer the actual application so far, the code examples we have seen do not reflect the actual use of ' defer '. In this section we will look at the practical application of ' defer '. You can use ' defer ' when a function should be called in an environment that is not related to the current code flow. We use a [' Waitgroup '] (https://studygolang.com/articles/12512) Code example to understand the meaning of this statement. We will first write a not using ' defer 'program, and then we will use ' defer ' to modify and see the benefits of ' defer '. "' Gopackage mainimport (" FMT "" Sync ") type rect struct {length intwidth int}func (R rect) area (WG *sync. Waitgroup) {if r.length < 0 {fmt. Printf ("rect%v ' s length should be greater than zero\n", R) WG. Done () Return}if R.width < 0 {fmt. Printf ("Rect%v ' s width should be greater than zero\n", R) WG. Done () Return}area: = R.length * r.widthfmt.printf ("rect%v's Area%d\n", R, area) WG. Done ()}func main () {var wg sync. WAITGROUPR1: = rect{-67, 89}r2: = rect{5, -67}r3: = rect{8, 9}rects: = []RECT{R1, R2, R3}for _, V: = Range Rects {WG. ADD (1) Go V.area (&WG)}wg. Wait () fmt. Println ("All go routines finished executing")} "[Run on Playground] (https://play.golang.org/p/kXL85U0Dd_) in the program above, We created the ' rect ' struct on line 8th and created the method ' area ' of ' rect ' on line 13th to calculate the rectangle's size. ' Area ' checks if the width of the rectangle is less than 0. If the width of the rectangle is less than 0, it will print out the corresponding hint, and if it is greater than 0, it will print out the area of the rectangle. The ' main ' function creates 3 ' rect ' Types of variables: ' R1 ', ' R2 ', and ' R3 '. In line 34th, we add these 3 variables to the ' rects ' slice. The slice then iterates through the ' for Range ' loop and calls the ' area ' method as a concurrent Go process (line 37th). We use 'Waitgroup WG ' to make sure that the ' main ' function will not end execution until the other coprocessor finishes executing. After the ' Waitgroup ' is passed as a parameter to the ' area ' method, the ' main ' function is notified in lines 16th, 21st, and 26th, indicating that the process has completed all tasks now. * * If you look closely, you will find ' WG. Done () ' is called only when the ' area ' function returns. ' WG. Done () ' should be called before ' area ' is going to be returned and is not related to the path of the code flow, so we can call ' defer ' only once to effectively replace the ' WG '. Multiple invocations of done () ' * *. We'll use ' defer ' to rewrite the code above. In the following code, we removed 3 ' WG ' from the original program. Done ' call, but with a separate ' defer WG. Done () ' to replace it (line 14th). This makes our code more concise and understandable. "' Gopackage mainimport (" FMT "" Sync ") type rect struct {length intwidth int}func (R rect) area (WG *sync. Waitgroup) {defer WG. Done () if R.length < 0 {fmt. Printf ("rect%v ' s length should be greater than zero\n", R) Return}if R.width < 0 {fmt. Printf ("Rect%v ' s width should be greater than zero\n", r) Return}area: = R.length * r.widthfmt.printf ("rect%v's area%d\n ", R, Area)}func main () {var wg sync. WAITGROUPR1: = rect{-67, 89}r2: = rect{5, -67}r3: = rect{8, 9}rects: = []RECT{R1, R2, R3}for _, V: = Range Rects {WG. ADD (1) Go V.area (&WG)}wg. Wait () fmt. Println ("All go routines finished executing")} "[InRun on Playground] (HTTPS://PLAY.GOLANG.ORG/P/JUUVYTLFBV) The program outputs: "Rect {8 9} ' s area, rect { -67) ' s length should be great Er than zero rect {5-67} ' s width should is greater than zero all go routines finished executing ' ' in the program above, use ' defer ' and a A benefit. Suppose we use the ' if ' conditional statement and add a return path to the ' area ' method. If you do not use ' defer ' to call ' WG '. Done () ', we have to be careful to make sure that the ' WG ' is called in this newly added return path. Done () '. Because now we delay calling the ' WG. Done () ', so there is no need to add ' WG ' to this new return path. Done () '. This concludes the tutorial. Have a nice day. * * Previous tutorial-[polymorphism] (https://studygolang.com/articles/12681) * * * Next tutorial-[Error handling] (https://studygolang.com/articles/12724) * *
via:https://golangbot.com/defer/
Author: Nick Coghlan Translator: Noluye proofreading: polaris1119
This article by GCTT original compilation, go language Chinese network honor launches
This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove
1958 Reads