1

I have this code

package main

import (
    "fmt"
)

type foo struct {
    a int
    b bool
}

type foos []foo

type bar struct {
    foos
}

func newBar() *bar {
    b := &bar{
        foos: make([]foo, 3, 3),
    }
    for _, foo := range b.foos {
        // didn't set b to true
        foo.b = true
    }
    return b
}

func main() {
    b := newBar()
    fmt.Println(b)
    // set b to true
    b.foos[0].b = true
    fmt.Println(b)
}

The Go Playground

As you can see I want to initialize bar using constructor newBar() but I want the embed type foo.b is initialize with non zero value so I initialize with for range statement but it didn't work as intended, the foo.b is still false, all of them. As comparison in the main function using this code b.foos[0].b = true it work. So whats wrong with my code?

1 Answer 1

1

Omg, I just realized this after posting this question, it's because variable slot is local to for loop. So the solution is:

for i, _ := range b.foos {
    // now b is set to true
    b.foos[i].b = true
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yes. In the case for _, foo := range b.foos {, each item in b.foos gets copied to foo, so changing foo will not be reflected in b.foos. The solution you suggest in your answer fixes it by referencing the original instances, without copying. If however b.foos were a slice of pointers to foo ( []*foo ), the pointer would have been copied but not the original value, so the for _, foo := range b.foos { would have worked as expected, given that you had first allocated each item.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.