emk
emk

Reputation: 185

Nested struct is not updated

I have a nested struct. I want to update it inside a method. For some reason, the update doesn't take place.

    package main

    import "fmt"

    type B struct {
        c int
    }

    type A struct {
        b B
    }

    func (a A) updateB(n int) {
        a.b.c = n
    }

    func main() {
        a := A{b: B{c: 5}}

        fmt.Println(a)
        a.updateB(42)
        fmt.Println(a)
    }

The output I get is

{{5}}
{{5}}

In most languages, I'd expect it to be updated. Is this some special Go behavior? How does one go about updating nested structs in Go?

Upvotes: 2

Views: 2707

Answers (4)

Ibu
Ibu

Reputation: 43810

The problem is with your update function. You are supposed to add it to the pointer to A.

func (a *A) updateB(n int) {
    a.b.c = n
}

Upvotes: 3

jonroethke
jonroethke

Reputation: 1162

It's not because the struct is nested, rather it's because you need a pointer receiver to modify the value to which the receiver points, in this case your a variable.

Without the pointer your UpdateB method would only be updating a copy of the original A struct value.

See the following:

package main

import "fmt"

type B struct {
    c int
}

type A struct {
    b B
}

func (a *A) UpdateB(n int) {
    a.b.c = n
}

func main() {
    a := A{b: B{c: 5}}

    fmt.Println(a)
    a.UpdateB(50)
    fmt.Println(a)
}

Upvotes: 3

pr0p
pr0p

Reputation: 2358

For any interface for its objects to be updated by a function you need to pass the object by reference.

package main

import "fmt"

type B struct {
    c int
}

type A struct {
    b B
}

func (a *A) updateB(n int) {
    a.b.c = n
}

func main() {
    a := A{b: B{c: 5}}

    fmt.Println(a)
    a.updateB(42)
    fmt.Println(a)
}

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

Upvotes: 1

Iain Duncan
Iain Duncan

Reputation: 3394

It is because you are using a value receiver so the updateB method receives a copy of the value of A rather than a pointer to the memory that contains the a variable. Using a pointer receiver fixes the problem:

package main

import "fmt"

type B struct {
    c int
}

type A struct {
    b B
}

func (a *A) updateB(n int) {
    a.b.c = n
}

func main() {
    a := A{b: B{c: 5}}

    fmt.Println(a)
    a.updateB(42)
    fmt.Println(a)
}

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

See also:

Value receiver vs. Pointer receiver in Golang?

Upvotes: 6

Related Questions