Order of execution between defer, return, and return values in Golang

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

Write go for some time, although you can also complete some of the API and some features of the development. But it's a long way from being a real go developer.

Let's summarize the error handling in the Go language today. It is important for beginners. The Go language delay function defer acts as a try...catch and is very easy to use, but in practice, many gopher do not really understand the order of execution between defer, return, and return values and fall into the pit.

The condition of the anonymous return value:

Package <textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">Mainimport ("FMT") func main () {FMT. Println ("A return:", A ())//Prints the result as a return:0}func a () int {var i intdefer func () {i++fmt. Println ("A defer2:", i)//prints the result as a defer2:2} () defer func () {i++fmt. Println ("A defer1:", i)//print the result is a defer1:1} () return i}</textarea>
12345678910111213141516171819202122 Package MainImport ("FMT")funcMain() {FMT.Println("A return:", a()) //Print result is a return:0}func a() int {var I intdeferfunc() {I++FMT.Println("a defer2:", I) //Print result is a defer2:2}()deferfunc() {I++FMT.Println("a defer1:", I) //Print result is a defer1:1}()return I}

Conditions for non-anonymous return values:

Package <textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">main Import ("FMT") func main () {FMT. Println ("B return:", B ())//Prints the result to B Return:2} func B () (i int) {defer func () {i++ fmt. Println ("B defer2:", i)//print result is b defer2:2} () defer func () {i++ fmt. Println ("B defer1:", i)//print the result is B defer1:1} () return I//or the direct return effect is the same}</textarea>
123456789101112131415161718192021 Package Main Import (    "FMT") funcMain() {    FMT.Println("B return:", b()) //Print results for B return:2} func b() (I int) {    deferfunc() {        I++        FMT.Println("b defer2:", I) //Print results for B defer2:2    }()    deferfunc() {        I++        FMT.Println("b defer1:", I) //Print results for B defer1:1    }()    return I //or direct return effect is the same}

    1. The order of execution of multiple defer is "LIFO";
    2. All functions will check for the existence of the defer statement before executing the RET return instruction, and if it exists, then call the defer statement in reverse order to finish the work before exiting back;
    3. The anonymous return value is declared at return execution, and the well-known return value is declared at the same time as the function declaration, so that only the named return value can be accessed in the defer statement, but not directly to the anonymous return value;
    4. The return should actually contain two steps: The first step is to assign a value to the return value (if the value of the return value is a direct assignment, if the anonymous return value is first declared and then assigned); the second step is to call the RET return instruction and pass in the return value, while RET checks to see if defer exists. If there is an inverted defer statement, the last RET carries the return value Exit function;

Therefore,the execution order of the defer, return, and return values should be: Return first assigns a value to the returned value; then defer begins to perform some finishing work; Finally the RET instruction carries the return value Exit function.

The return value of the A () int function is not well-known, its value is derived from the assignment of other variables, and the other variables are modified in defer (in fact, the defer is not directly accessible to the return value), so the return value is not modified when the function exits.

The return value of the B () (I int) function is well known in advance, which allows defer to access the return value, so that after the return assignment returns the value I, the defer invokes the return value I and modifies it. The return value after the return call to the RET Exit function will be the defer modified value.

Package <textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">main Import ("FMT") func main () {c:=c () fmt. Println ("C return:", *c, C)//print result for C Return:2 0xc082008340} func C () *int {var i int defer func () {i++ Fmt. Println ("C Defer2:", I, &i)//Prints the result as C Defer2:2 0xc082008340} () defer func () {i++ fmt. Println ("C defer1:", I, &i)//print result C defer1:1 0xc082008340} () return &i}</textarea>
1234567891011121314151617181920212223 Package Main Import (    "FMT") funcMain() {    C:=C()    FMT.Println("C return:", *C, C) //Print results for C Return:2 0xc082008340} func C() *int {    var I int    deferfunc() {        I++        FMT.Println("C Defer2:", I, &I) //Print results for C defer2:2 0xc082008340    }()    deferfunc() {        I++        FMT.Println("C Defer1:", I, &I) //Print results for C defer1:1 0xc082008340    }()    return &I}

Although the return value of the C () *int is not declared in advance, since the return value of the C () *int is a pointer variable, after return assigns the address of the variable I to the return value, defer modifies the actual value of I in memory again, As a result, the return value returned when calling the RET exit function is still the original pointer address, but the actual value of the memory it points to has been successfully modified.

Reference: http://my.oschina.net/henrylee2cn/blog/505535

order of execution between defer, return, and return values in Golang
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.