Go language's defer is considered a new feature of the language, at least compared to today's mainstream programming languages.
The defer statement calls a function. The execution of this function will be postponed until the peripheral function returns, or the peripheral function runs to the end, or the corresponding goroutine panics
Whenever defer is executed, it The subsequent function value (in Go, the function is a reference type, a first-class citizen, and can be assigned to a variable) and function parameters will be evaluated, but the function will not be called immediately until (↑) the above three situations occur. This is the whole content of defer, gone, the rest is the best practice of defer
The function will not be called immediately
Start with the simplest one:
func readFile(fileName string){ f,err := os.Open(fileName) if err!=nil { return } defer f.Close() var content [1024]byte f.Read(content[:]) fmt.Printf("%s",content) } func main() { readFile("test.data") }
The program outputs the first 1024 bytes of test.data. It is worth mentioning that open/close pairing operations like this are the idiomatic usage of defer. This example explains the second half of the above sentence
"But the function will not be called"
Because if f.Close() after defer is not delayed, then the file descriptor If they are all closed, nothing will be read.
The function value and function parameters are evaluated, but the function is not called immediately
The following example will explain the first half, it comes from <>, slightly Modification:
func trace(funcName string) func(){ start := time.Now() fmt.Printf("function %s enter\n",funcName) return func(){ log.Printf("function %s exit (elapsed %s)",funcName,time.Since(start)) } } func foo(){ defer trace("foo()")() time.Sleep(5*time.Second) } func main(){ foo() foo() } /* OUTPUT: function foo() enter function foo() exit (elapsed 5.0095471s) function foo() enter function foo() exit (elapsed 5.0005382s) */
Why does foo output enter and then wait for about five seconds before outputting exit? Because as we said, the function value and parameters after
defer will be evaluated but the actual function The call has to wait until the end
The function value here is the anonymous function returned by trace(). The function parameter is of course the string literal value "foo()". The evaluation of trace("foo()") will Output function foo() enter, the actual function call trace("foo()")(), that is, the output function foo() exit(elapsed x.x) will be postponed until return execution (if return will update the return value variable, it will be executed after the update before executing the defer function).
Miscellaneous
To say a little more, if there are multiple defer statements, the execution order of the last defer function is opposite to the order in which defer appears, such as:
func main() { func1 := func(){ fmt.Println("func1() execution deferred") } func2 := func(){ fmt.Println("func2() execution deferred") } defer func1() defer func2() fmt.Println("strat\nworking...") } /* OUTPUT: strat working... func2() execution deferred func1() execution deferred */
The above is the detailed content of Introduction to go defer (go delay function). For more information, please follow other related articles on the PHP Chinese website!