Home  >  Article  >  Backend Development  >  What is the relationship between defer and panic in Go language?

What is the relationship between defer and panic in Go language?

王林
王林Original
2023-06-11 09:00:08891browse

The Go language is a new programming language that has added some unique syntax and features, among which defer and panic are two very important features. This article will introduce the relationship between defer and panic in Go language as well as their usage and characteristics.

Usage of defer

The defer statement in Go language is used to register a function. When the execution of this function ends or the current scope ends, the registered function will be automatically executed. defer can be used in multiple scenarios such as resource release, lock unlocking and error handling.

The following is an example of defer releasing resources:

func main() {
    file, err := os.Open("myfile.txt")
  // 在函数结束时,会自动关闭文件
    defer file.Close()
  
    if err != nil {
        fmt.Println("Failed to open file.")
        return
    }
    // ...
}

It is registered through the Close() function of the defer file, and the file will be automatically closed when the function execution ends.

The following is an example of unlocking a defer lock:

func main() {
    var lock sync.Mutex
    lock.Lock()
  // 当函数执行结束时,会自动解锁
    defer lock.Unlock()
  
    // ...
}

When the function execution ends, the Unlock() function will be automatically called to unlock the lock.

The execution order of defer is from back to front, which means that if multiple defer statements are registered, they will be executed in the reverse order. The following example will output Defer 2, and then Defer 1.

func main() {
    defer fmt.Println("Defer 1")
    defer fmt.Println("Defer 2")
    fmt.Println("Hello")
}

Usage of panic

The panic keyword in Go language is used to throw an exception and terminate the execution of the current function or program. Panics will propagate up the function call stack until they are caught by the recover() function. If not caught, the entire program is exited and a call stack is printed.

In the following example code, when the length of the input string is less than 5, a panic will be triggered and the execution of the program will be terminated.

func hello(name string) {
    if len(name) < 5 {
        panic("Name is too short.")
    }
    fmt.Println("Hello", name)
}

func main() {
    hello("Tom")
    hello("Bob")
    hello("me")
}

The output result is as follows:

Hello Tom
Hello Bob
panic: Name is too short.

goroutine 1 [running]:
main.hello(...)
    /Users/user/goland/src/main.go:4
main.main()
    /Users/user/goland/src/main.go:10 +0x81
exit status 2

Here we can see that when the input name is me, panic will be triggered and program execution will be terminated.

The relationship between defer and panic

panic plays the role of immediately terminating program execution, which means that it can be triggered at any time, including before the end of function execution. In order to ensure that the program can release resources in time and perform some necessary cleanup work, the Go language introduces the defer mechanism, which allows the function to perform some cleanup operations before exiting.

When a panic is triggered in a function, it will exit immediately and execute all defer functions registered before the current function. The following example code manually triggers a panic and executes the defer function twice before exiting.

func main() {
    defer fmt.Println("Defer 1")
    defer fmt.Println("Defer 2")
    
    panic("Oops! Something went wrong.")
}

The output results are as follows:

Defer 2
Defer 1
panic: Oops! Something went wrong.

goroutine 1 [running]:
main.main()
    /Users/user/goland/src/main.go:7 +0x81
exit status 2

We can see that after triggering the panic, the two defer functions are executed in reverse order.

In addition to registering the defer function at the end of the function, the Go language also allows multiple defer functions to be registered in the function. This means that if there are multiple defer functions in a function, even if one of the defer triggers a panic, the other defer functions can still be executed.

The following example code demonstrates that when a function registers multiple defer statements, one of the defer functions triggers a panic, but the other defer functions are still executed.

func init() {
    fmt.Println("Init 1")
}

func init() {
    fmt.Println("Init 2")
}

func main() {
    defer fmt.Println("Defer 1")
    
    defer func() {
        if err := recover(); err != nil {
            fmt.Println("Recovered:", err)
        }
    }()
    
    defer fmt.Println("Defer 2")
    
    panic("Oops! Something went wrong.")
}

The output results are as follows:

Init 1
Init 2
Defer 2
Recovered: Oops! Something went wrong.
Defer 1

We can see that the function first executes two init functions, and then executes three defer functions in sequence. When one of the defers triggers a panic, but is caught by another defer and the program is resumed, eventually both defer functions execute normally.

In actual development, defer and panic are often used in pairs. defer is used to release resources and perform cleanup operations, and panic is used to handle exceptions. When a function needs to perform multiple cleanup operations before exiting, we can use a defer wrapper function at the beginning of the function and use the recover() function to prevent the function from exiting early. This way of writing is very common and provides a strong guarantee for us to write robust programs.

The above is the detailed content of What is the relationship between defer and panic in Go language?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn