Home  >  Article  >  Backend Development  >  Introduction to go defer (go delay function)

Introduction to go defer (go delay function)

尚
forward
2019-11-30 14:03:382297browse

Introduction to go defer (go delay function)

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 a8093152e673feb7aba1828c43532094, 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!

Statement:
This article is reproduced at:cnblogs.com. If there is any infringement, please contact admin@php.cn delete