Home >Backend Development >Golang >How to Correctly Use Defer in Go When Dealing with Changing Local Variables?

How to Correctly Use Defer in Go When Dealing with Changing Local Variables?

Susan Sarandon
Susan SarandonOriginal
2024-12-10 13:55:14179browse

How to Correctly Use Defer in Go When Dealing with Changing Local Variables?

Defer Usage Clarification: Printing Final Variable Value

In Go, the defer keyword allows us to schedule a function to be executed just before the surrounding function returns. However, if the deferred function uses local variables that may change within the surrounding function, special care must be taken to ensure the correct values are used.

Consider the following function:

func printNumbers() {
    var x int

    defer fmt.Println(x)

    for i := 0; i < 5; i++ {
        x++
    }
}

According to the language specification, when the defer statement executes, the local variables are evaluated and saved anew. However, the actual function is not invoked until later. In this case, when the defer statement is executed, the value of x is 0, so 0 will be printed when the deferred function is invoked.

To resolve this issue, we can use one of several approaches:

1. With Anonymous Function:

defer func() { fmt.Println(x) }()

This uses an anonymous function that captures the current value of x. When the anonymous function is invoked, it will use the captured value, even if x has changed in the surrounding function.

2. With Pointer:

var x int
defer Print(&x)

We can use a pointer to x and defer a function that prints the pointed value. This works because the pointer value is evaluated when the defer statement executes, but the pointed value is not evaluated until the deferred function is invoked.

3. With Custom Type:

type MyInt int
func (m *MyInt) String() string { return strconv.Itoa(int(*m)) }
var x MyInt
defer fmt.Println(&x)

Here, we create a custom type MyInt that implements the fmt.Stringer interface, allowing us to specify how the value is printed. When &x is printed, the String method will be called, returning the string representation of the pointed value.

4. Wrapping:

x := []int{0}
defer fmt.Println(x)

Wrapping the variable in a slice allows us to defer a function that prints the slice content. The slice descriptor is evaluated when the defer statement executes, but the underlying array is not evaluated until the deferred function is invoked.

It's important to remember that the variable being used in the deferred function should not be a parameter of the deferred function itself, as the parameters are evaluated when the defer statement executes.

The above is the detailed content of How to Correctly Use Defer in Go When Dealing with Changing Local Variables?. 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