2

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?

emk
  • 175
  • 1
  • 11

4 Answers4

6

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?

Iain Duncan
  • 3,139
  • 2
  • 17
  • 28
3

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
}
Ibu
  • 42,752
  • 13
  • 76
  • 103
3

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)
}
jonroethke
  • 1,152
  • 2
  • 8
  • 16
1

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

Prajval M
  • 2,298
  • 11
  • 32