Home  >  Article  >  Backend Development  >  For the same structure, Golang behaves differently in defer in for loop

For the same structure, Golang behaves differently in defer in for loop

WBOY
WBOYforward
2024-02-06 09:30:11932browse

对于同一结构体,Golang 在 for 循环中 defer 的行为有所不同

Question content

I wrote the following golang code and ran it.

type test struct {
    name string
}

func (t test) hello() {
    fmt.printf("hello, %s\n", t.name)
}

func (t *test) hello2() {
    fmt.printf("pointer: %s\n", t.name)
}

func runt(t test) {
    t.hello()
}

func main() {
    mapt := []test{
        {name: "a"},
        {name: "b"},
        {name: "c"},
    }

    for _, t := range mapt {
        defer t.hello()
        defer t.hello2()
    }
}

Output:

pointer: C
Hello, C
pointer: C
Hello, B
pointer: C
Hello, A

My understanding is that the pointer t will point to "c" after 3 loops, so the three 3 "c"s are used for the "hello2" output. However, delaying the "hello" function call behaves very strangely. It looks like it's retaining the location it points to. (t test) How to affect this?

I'm curious as to what golang compiles this into. Thank you so much!


Correct answer


In the for loop, the parameter of the defer statement is a closure. The closure captures the loop variable t.

For calls using a value receiver, the closure contains a copy of t. For calls using pointer receivers, the closure contains a pointer to t.

Loop variables are rewritten on each iteration (this behavior will change in later versions of the language). Therefore, value receiver closures capture every value, while pointer receiver closures only capture the pointer, so at runtime they use the latest value of that pointer.

The above is the detailed content of For the same structure, Golang behaves differently in defer in for loop. For more information, please follow other related articles on the PHP Chinese website!

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