Defer keywords in the Go language

Source: Internet
Author: User
Tags documentation


An explanation of the defer statement in the official documentation:

The defer statement delays execution of a function that is deferred until the program that contains it returns (the function that contains it executes the return statement/run to the end of the function automatically returns/corresponds to the goroutine panic) execution.

Each time the defer statement executes, the return value and parameter values of the defer decorated function are evaluated and saved as usual, but the function does not execute. Until the previous function returns, all defer functions are executed in reverse order of the defer declaration. Any return value of the defer function will be discarded.

If the function value of a defer is nil, then this defer function panic (exception) when the function is executed, but not panic when the defer statement executes, for example:

Func Test () {

F: = func () {fmt. Println ("Test")}

Defer f ()

F = nil//The value of the function is set to nil here, and then when you try to execute the function

Defer f ()

Defer FMT. Println ("Test1")

}

Func Main () {

Test ()

}

Execution Result:

Test1

Test

Panic:runtime Error:invalid memory address or nil pointer dereference

[Signal 0xc0000005 code=0x0 addr=0x0 pc=0x451668]

Goroutine 1 [Running]:

Panic (0X49AAA0, 0xc042004090)

D:/program files/go/src/runtime/panic.go:500 +0X1AF

Main.test ()

D:/programming/gowork/defer.go:28 +0XFC

Main.main ()

D:/programming/gowork/defer.go:31 +0x1b

As can be seen, the first Test1 normal output, after setting F = nil, defer f () is not directly panic, but before the test () is returned, the reverse execution to the second F (), throw an exception. The test is also output, indicating that the defer method will be executed before panic, and will not be stopped because of panic, the contrast test:

Func Test () {

F: = func () {fmt. Println ("Test")}

F ()

F = Nil

F ()

Fmt. Println ("Test1")

}

Func Main () {

Test ()

}

Execution Result:

Test

Panic:runtime Error:invalid memory address or nil pointer dereference

[Signal 0xc0000005 code=0x0 addr=0x0 pc=0x40107a]

Goroutine 1 [Running]:

Panic (0X49AA20, 0xc042004090)

D:/program files/go/src/runtime/panic.go:500 +0X1AF

Main.test ()

D:/programming/gowork/defer.go:26 +0x3a

Main.main ()

D:/programming/gowork/defer.go:31 +0x1b

Exit Status 2

You can see that the Test1 is not output because the FMT is being executed. Println ("Test1") before Test () has panic.

To interrupt a panic processing method:

The built-in method recover () can capture the Panic,recover () method with a return value, and if recover () captures panic, the panic object is returned, otherwise nil is returned. Here is an example of an recover () in the official documentation that encapsulates a method to capture panic (similar to Try...catch ... ):

Func Test () {

F: = func () {fmt. Println ("Test")}

F ()

F = Nil

F ()

Fmt. Println ("Test1")

}

Func Safefunc (target func ()) {

Defer func () {

If x: = Recover (); X! = Nil {

Fmt. Println ("Runtime Panic:", X)

}

} ()

Target ()

}

Func Main () {

Safefunc (Test)

}

Execution Result:

Test

Runtime panic:runtime error:invalid memory address or nil pointer dereference

You can use the panic () function to manually throw a panic:

Panic ("Error Message")

Back to the usage of defer, here are a few examples to illustrate the use of defer:

Example 1:

Func Main () {

For I: = 0; I < 3; i++ {

Defer FMT. Println (i)

}

}

Output: 2 1 0

The above code is equivalent to:

Func Main () {

Defer FMT. PRINTLN (0)//each time the defer statement executes, the return value and parameter values of the defer decorated function are calculated and saved as usual

Defer FMT. PRINTLN (1)//similarly

Defer FMT. PRINTLN (2)//similarly

}

That

Func Main () {

Fmt. PRINTLN (2)

Fmt. PRINTLN (1)

Fmt. PRINTLN (0)

}

Example 2:

Func Main () {

For I: = 0; I < 3; i++ {

Defer func () {fmt. Println (i)} ()

}

}

Output:

3 3 3

The above code is equivalent to:

Func Main () {

I: = 0

Defer func () {fmt. Println (i)} ()///defer modifier is a closed function, not a FMT statement inside, so the parameters inside are unchanged

i++//i = 1

Defer func () {fmt. Println (i)} ()

i++//I = 2

Defer func () {fmt. Println (i)} ()

i++//I = 3

}

That

Func Main () {

I: = 0

i++

i++

i++

Func () {fmt. Println (i)} ()

Func () {fmt. Println (i)} ()

Func () {fmt. Println (i)} ()

}

Example 3:

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.