1

I've been trying to update a map variable inside a struct but with no luck.

I expected that maps in Golang are passed by reference and hence assigning one reference to another should work but that's not the case.

I might be missing something obvious here, and if that's the case, apologies!

package main

import (
        "fmt"
)

type Foo struct {
        t map[string]interface{}
}

func (F Foo) Set(ta map[string]interface{}) {
        F.t = ta
}
func (F Foo) Get() map[string]interface{} {
        return F.t
}

func main() {
        t := make(map[string]interface{})
        t["t"] = "sf"
        t["array"] = []int{1, 2, 3}

        fmt.Println(t) // prints map[t:sf array:[1 2 3]]
        var f Foo

        f.Set(t)
        // why the following?
        fmt.Println(f.t) //prints map[]

        f.t = t
        fmt.Println(f.t) //prints map[t:sf array:[1 2 3]]
}

Playground: https://play.golang.org/p/i1ESV1BdjGQ

1 Answer 1

2

Basically, you need a pointer receiver on your Set method to be able to change the state of your structure.

Methods with pointer receivers can modify the value to which the receiver points. Since methods often need to modify their receiver, pointer receivers are more common than value receivers.

Get should also have a pointer receiver for consistency:

Next is consistency. If some of the methods of the type must have pointer receivers, the rest should too, so the method set is consistent regardless of how the type is used. See the section on method sets for details.

See a tour of go for more examples.

Here is a fix of your code:

package main

import (
    "fmt"
)

type Foo struct {
    t map[string]interface{}
}

func (F *Foo) Set(ta map[string]interface{}) {
    F.t = ta
}
func (F *Foo) Get() map[string]interface{} {
    return F.t
}

func main() {
    t := make(map[string]interface{})
    t["t"] = "sf"
    t["array"] = []int{1, 2, 3}

    fmt.Println(t)
    var f Foo

    f.Set(t)
    fmt.Println(f.Get()) //prints map[t:sf array:[1 2 3]]

    f.t = t
    fmt.Println(f.Get()) //prints map[t:sf array:[1 2 3]]
}

Outputs

map[t:sf array:[1 2 3]]
map[t:sf array:[1 2 3]]
map[t:sf array:[1 2 3]]

Try it yourself here

Sign up to request clarification or add additional context in comments.

4 Comments

Okay, this was embarrassing. But then, I've a problem with satisfying an Interface.. Playground: play.golang.org/p/-mPPGyEv5yD
Now the thing is that since you have methods with pointer receivers, you need to have a pointer to your struct for it to work properly, which is why usually structures are instanciated like x := &X{} or using a func NewX() *x of some kind
Thank you so much! I already was aware of this gotcha in Go but just couldn't figure it out. Thanks a lot!!
Glad I could help :)

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.