0

With this code: https://play.golang.org/p/tCm1W-K-6ob

This code would print: [c c c], but [a b c] is excepted.

type A struct {
    a *string
}

func f() {
    slist := []string{"a", "b", "c"}
    list := make([]*A, len(slist))
    for i, v := range slist {
        item := &A{
            a: &v,
        }
        list[i] = item
    }
    fmt.Printf("[%s %s %s]", *list[0].a, *list[1].a, *list[2].a)
}

func main() {
    f()
}

Why the list is not ["a", "b", "c"]? What happened to the range or the &string?

  • 1
    Loop variables in Golang is actually shared for all iterations of the loop similar to JS, so `i` and `v` are the same variables for the whole loop. So you need to create a temp value for v if you want to get the address. – SwiftMango Jul 09 '19 at 03:15

4 Answers4

1

https://play.golang.org/p/utJrUmxeqfh

package main

import (
    "fmt"
)

func main() {
    foo := []int{1, 2, 3}
    for _, f := range foo {
        fmt.Printf("value is %d, addr is %p \n", f, &f)
    }
    fmt.Println("Hello, playground")
}
value is 1, addr is 0x414020 
value is 2, addr is 0x414020 
value is 3, addr is 0x414020 
Hello, playground

the value f in range has the same address

beiping96
  • 644
  • 3
  • 12
1

The items all contain the address of the one local variable v.

If your goal is to assign the address of the slice element the a field, then do the following:

for i := range slist {
    item := &A{
        a: &slist[i],  // address of element instead of local variable.
    }
    list[i] = item
}

Run it on the Go Playground.

You can also get the output you want by creating a new variable on each loop iteration:

for i, v := range slist {
    v := v  // create new value on each iteration.
    item := &A{
        a: &v,
    }
    list[i] = item
}

Run it on the Go Playground.

Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
0

The thing is that the iterator variable is allocated only once and the value it points to is changed with each iteration of the loop:

package main

import (
    "fmt"
)

type A struct {
    a *string
}

func f() {
    slist := []string{"a", "b", "c"}
    list := make([]*A, len(slist))

    // v is only allocated once and the value at it's address is changed
    // on each iteration.
    for i, v := range slist {
        fmt.Printf("Iteration %d: address of v %#v, value of v \"%s\"\n", i+1, &v, v)
        // Add in a temp variable, which will get allocated
        // and hence have a new address each iteration.
        t := v

        // Now assign that temp variable's address to the Item's a.
        list[i] = &A{
            a: &t,
        }
    }
    fmt.Printf("[%s %s %s]", *list[0].a, *list[1].a, *list[2].a)
}

func main() {
    f()
}

Run on playground

However, I have a strong feeling that this is unintuitive because we are pretty much talking of premature optimization. (A bit simplified): A string in Go is basically a slice of bytes([]byte), with a slice already being a pointer to the backing array. See Go Slices: usage and internals for details.

Markus W Mahlberg
  • 19,711
  • 6
  • 65
  • 89
-2

You can try this

Here I can run your code and do some changes.

https://play.golang.org/p/GmU3goeOKdF

here is code

package main

import (
    "fmt"
)

type A struct {
    a  *string
}

func f() {
    slist := []string{"a", "b", "c"}
    list := make([]*A, len(slist))
    for i, v := range slist {
        item := &A{
            a: &v,
        }
        list[i] = item

    fmt.Printf("%s", *list[i].a)
    }
}
func main() {
    f()
}

Output abc

Anshu
  • 1,277
  • 2
  • 13
  • 28
  • You can see the answer..I think its helpful to you. @shougang – Anshu Jul 09 '19 at 03:20
  • Link only answers do not help much. Should the link change or vanish, the answer becomes meaningless. Please include at least the gist in your answer. – Markus W Mahlberg Jul 09 '19 at 06:27
  • @MarkusWMahlberg ,i am try to solve their question. so that i can only run code and do the some changes. – Anshu Jul 09 '19 at 06:57
  • I understand that. But for the sake of long term knowledge retention, it makes sense to actually answer the question here completely, with links only adding information. Please see https://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers for an in depth discussion why link-only anwers should be avoided. – Markus W Mahlberg Jul 09 '19 at 07:03