Home > Backend Development > Golang > Why does Go's `append` function produce unexpected results when appending pointers from a for-range loop?

Why does Go's `append` function produce unexpected results when appending pointers from a for-range loop?

Linda Hamilton
Release: 2024-12-22 22:35:15
Original
756 people have browsed it

Why does Go's `append` function produce unexpected results when appending pointers from a for-range loop?

Unexpected Append Behavior with Go Slices: An Explanation

In Go, the append function behaves intriguingly when appending to a slice of pointers. To illustrate this, consider the following code:

import "fmt"

type Foo struct {
    val int
}

func main() {
    var a = make([]*Foo, 1)
    a[0] = &Foo{0}

    var b = [3]Foo{Foo{1}, Foo{2}, Foo{3}}
    for _, e := range b {
        a = append(a, &e)
    }

    for _, e := range a {
        fmt.Printf("%v ", *e)
    }
}
Copy after login

Contrary to one's expectation that the code would print {0} {1} {2} {3}, it instead prints {0} {3} {3} {3}. The reason behind this discrepancy lies in the nature of the for loop's range variable.

Understanding the Range Variable

The for-range loop in Go operates by creating a copy of each element in the array or slice being iterated over. In this case, e is a copy of the element in the array b. Hence, e itself is not the element in b; rather, it's a temporary variable holding the value of the element.

When appending to the slice a, the code is appending the address of e, not the address of the actual element in b. Since e is the same copy for all iterations, the same pointer is appended to a three times. Thus, the last value assigned to e (which is Foo{3}) is the one printed repeatedly.

Fixing the Behavior

To rectify this behavior, the code should append the address of the actual element in b, not the address of e. The corrected loop would look like this:

for i := range b {
    a = append(a, &b[i])
}
Copy after login

By appending &b[i] instead of &e, the code ensures that each element in b is added to a. Consequently, the correct output {0} {1} {2} {3} is printed.

Reason for the Initial Behavior

This unexpected behavior stems from the absence of true references in Go. Go has pointer types and non-pointer types, but not references. The range variable is simply a local variable, holding a value that may be a pointer or a non-pointer. It cannot hold a reference.

Therefore, when operating on the range variable, one is only manipulating the value, not the element itself. To modify the actual element, one must assign the value to the range variable, effectively copying the value. This value is then overwritten in the next iteration.

The above is the detailed content of Why does Go's `append` function produce unexpected results when appending pointers from a for-range loop?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template