This is a creation in Article, where the information may have evolved or changed.
Defer
Grammar:
Simply put, this function of defer is executed automatically after the defer function executes all the code.
Example one (basic function)
package mainimport "fmt"/*D:\examples>go run helloworld.gofirstsecondD:\examples>*/func main() { defer second() first()}func first() { fmt.Println("first")}func second() { fmt.Println("second")}
Example two (function locality)
package mainimport "fmt"/*D:\examples>go run helloworld.gofirstthirdfirstsecondD:\examples>*/func main() { defer second() first() third()}func first() { fmt.Println("first")}func second() { fmt.Println("second")}func third() { defer first() fmt.Println("third")}
Example three (stack feature)
package mainimport "fmt"/*D:\examples>go run helloworld.gofirstthirdsecondD:\examples>*/func main() { defer second() defer third() first()}func first() { fmt.Println("first")}func second() { fmt.Println("second")}func third() { fmt.Println("third")}
Usage Scenarios
Used primarily for scenarios where resources need to be released. For example, open a file, and then always close it. In between open and close, there will be a lot of processing, there may be many if-else, according to different circumstances need to return early. In traditional languages, it takes one by one to call Close () before return.
And go's defer will make things simple, after open (), directly with the defer "register" a close (). Pseudo code:
f, = os.open(filename)defer f.close()do_something()if (condition_a) {return}do_something_again() if (condition_b) {return}do_further_things()
Panic & Recover
The function description on https://golang.org/pkg/builtin/is given first.
Panic
func panic(v interface{})
The panic built-in function stops normal execution of the current goroutine. When a function f calls panic, normal execution of F stops immediately. Any functions whose execution is deferred by F is run in the usual a, and then F returns to its caller. To the caller G, the invocation of F then behaves like a call to panic, terminating G's execution and running any deferred Functions. This continues until all functions in the executing goroutine has stopped, in reverse order. at (that), the program is terminated and the error condition are reported, including the value of the argument to panic . This termination sequence are called panicking and can be controlled by the built-in function recover.
Recover
func recover() interface{}
The Recover built-in function allows a program to manage behavior of a panicking goroutine. Executing a call-to-recover inside a deferred function (but no function called by it) stops the panicking sequence by Restoring normal execution and retrieves the error value passed to the call of panic. If recover is called outside the deferred function it would not stop a panicking sequence. In this case, or when the goroutine are not panicking, or if the argument supplied to panic was nil, recover returns nil. Thus the return value from recover reports whether the goroutine is panicking.
Points
- Panic equivalent to a run-time exception
- When encountering panic, the remaining statement of the current function is stopped, but the defer statement is executed before exiting the function.
- Based on the function call hierarchy, panic terminates each function sequentially until main ().
Panic Example
package mainimport "fmt"/*D:\examples>go run helloworld.gof.1g.1h.1h.defer()g.defer()panic: panic in h()goroutine 1 [running]:panic(0x495360, 0xc04203a230) C:/Go/src/runtime/panic.go:500 +0x1afmain.h() D:/examples/helloworld.go:54 +0x12bmain.g() D:/examples/helloworld.go:45 +0xeemain.f() D:/examples/helloworld.go:38 +0xabmain.main() D:/examples/helloworld.go:29 +0x1bexit status 2D:\examples>*/func main() { f() // Line Number: 29}func final_print(msg string) { fmt.Println(msg)}func f() { fmt.Println("f.1") g() // Line Number: 38 fmt.Println("f.2")}func g() { defer final_print("g.defer()") fmt.Println("g.1") h() // Line Number: 45 fmt.Println("g.2")}func h() { defer final_print("h.defer()") fmt.Println("h.1") panic("panic in h()") // Line Number: 52 fmt.Println("h.2")}
Panic & defer & Recover
The recover corresponds to the catch portion of the try-catch, making the panic no longer passed. and defer equivalent to the final part of Try-catch-final.
package mainimport "fmt"/*D:\examples>go run helloworld.gof.1g.1h.1h.defer()g.defer()panic in h()f.2D:\examples>*/func main() { f()}func final_print(msg string) { fmt.Println(msg)}func f() { fmt.Println("f.1") g() fmt.Println("f.2")}func g() { defer func() { str := recover() fmt.Println(str) }() defer final_print("g.defer()") fmt.Println("g.1") h() fmt.Println("g.2")}func h() { defer final_print("h.defer()") fmt.Println("h.1") panic("panic in h()") fmt.Println("h.2")}
Get array elements
Next, give an example, get array elements, handle the problem of array access.
Package Mainimport "FMT"/*d:\examples>go run helloworld.goa[0]=1[true]a[1]=2[true]a[2]=3[true]a[3]=4 [True]a[4]=5[true]runtime Error:index out of range [set to default Value-1]a[5]=-1[false]runtime Error:index out of Ran GE [set to default Value-1]a[6]=-1[false]runtime error:index out of range [set to default Value-1]a[7]=-1[false]runtime Error:index out of range [set to default Value-1]a[8]=-1[false]runtime error:index out of range [set to default value -1]a[9]=-1[false]d:\examples>*/func Main () {a: = [5]int {1,2,3,4,5} for I: = 0; i <; i++ {item, OK : = Get (i, a) fmt. Printf ("a[%d]=%d[%v]\n", I, item, OK)}}func get (i int, a [5]int) (ret int, OK bool) {OK = True defer func () { ERR: = Recover () if err! = Nil {fmt. Println (Err, "[set to Default Value-1]") ret =-1 OK = False}} () ret = A[i] Retu RN}