0

I would like to set a default value and if this is not set in a structure, I would like to set it. It's a bit confusing, but please take a look to the (simplified) code:

package main

import "log"

type Something struct {
    A string
    B map[string]Type
    C Epyt
}
type Type struct {
    A Epyt
    B string
}

type Epyt struct {
    A string
    B string
}

func main() {
    var a Something
    a.A = "Test A (Something)"
//  var a.B["one"] Type
    a.B["one"].A.A = a.B["one"].A.A
    a.B["one"].A.A = "Test A ([one]Type.Epyt)"
    a.B["two"].A.A = "Test A ([two]Type.Epyt)"  
    a.C.A = "Test A (Epyt)"
    a.C.B = "Test B (Epyt)"

    for i := range a.B {
        if a.B[i].A.B == "" {
            a.B[i].A.B = a.C.B
        }
    }
    log.Printf("%+v", a)
}

I'm working with viper to unmarshal a config file, therefor I'm not able to use pointers (or am I wrong?).

The error I'm getting, is cannot assign to struct field *** in map.

I found that this is an old bug in go lang still not corrected.

I've read Why do I get a "cannot assign" error when setting value to a struct as a value in a map? and Golang: I have a map of structs. Why can't I directly modify a field in a struct value? but as I said, I can't operate with pointers (or?), therefor please don't mark this as duplicate as it is not!

If someone has an idea on how to do this right, please help!

Boštjan Bele
  • 23
  • 1
  • 5
  • a.B is map as such you can not reference a field of it. If you want to access a field of an object in the map you will need to use a key like you do above a.B["two"].A.B = a.CB. If you want to do this to every member of the map you should use a loop – Benjamin Kadish May 07 '18 at 19:59
  • Thank you, Benjamin! I've corrected the code in the question as this was a typo in writing this simple code. Still need help! – Boštjan Bele May 07 '18 at 20:08
  • Where are you getting the error? `a.C.A = "Test A (Epyt)"` is definitely wrong, but doesn't have anything to do with maps. – Vitruvie May 07 '18 at 20:19
  • @BoštjanBele What makes you think you cannot unmarshal into a map of pointers? Did you try it? – mkopriva May 07 '18 at 20:21
  • 1
    This is a duplicate of https://stackoverflow.com/questions/32751537/why-do-i-get-a-cannot-assign-error-when-setting-value-to-a-struct-as-a-value-i and others. These other questions can also be made to work by using pointers. There is not a bug to correct in Go. Map values are not addressable. – Charlie Tumahai May 07 '18 at 20:21
  • @BoštjanBele is see no problem here https://play.golang.org/p/sWeiGlMfQn_3 although you haven't shared what data type you're unmarshaling with viper, so maybe it doesn't work with your case and if that's the case then you should share that information. – mkopriva May 07 '18 at 20:25
  • @mkopriva I have tried it with pointers and got an error (memory issue - usually when pointer is lost) – Boštjan Bele May 08 '18 at 08:18
  • @BoštjanBele A pointer doesn't just get lost unless you set it to `nil`. You still haven't shared what the config file type is, and how exactly you're unmarshaling that config. Also I would like to know where you read that this is an old bug? As far as I know this isn't a bug but I may be wrong and would like to read more about it. – mkopriva May 08 '18 at 08:26
  • @BoštjanBele basically your code is invalid because you're trying to set values on a non-pointer struct inside a map. That's just not allowed. You should use pointers to structs if you want to set the fields directly from the map. That's one option. The only other option you have is to retrieve the whole struct from the map into a variable, set its fields using the variable and then reinsert the struct back into the map using the same key that you've used to retrieve the struct. – mkopriva May 08 '18 at 08:30
  • @BoštjanBele if you have trouble using maps of pointers you should share the code that is casuing the problem. E.g. how the map is filled with data, how your trying to access that data, and what errors are you getting when accessing that data. Provide the error message, the stack trace, etc. – mkopriva May 08 '18 at 08:33
  • Possible duplicate of [Access Struct in Map (without copying)](https://stackoverflow.com/questions/17438253/access-struct-in-map-without-copying) – kostix May 08 '18 at 13:15
  • @mkopriva I played around a bit and got it working! I thought there is an error, because if I use printf over the whole structure, I get the address instead of the value back. Sorry for the inconvenience! – Boštjan Bele May 08 '18 at 13:49

2 Answers2

1

I played around a bit and got it working! I thought there is an error, because if I use printf over the whole structure, I get the address instead of the value back. Sorry for the inconvenience!

As @mkopriva told me, I tried to use pointers. After some errors I got it to work so far! Sorted out this brain bug ;)

Thank you again!

Boštjan Bele
  • 23
  • 1
  • 5
1

You haven't initialised the map.

Try

var a Something
a.B = make(map[string]Type)

Also, none of the structures you're referring to exist.

Ie, instead of:

a.B["one"].A.A = ...

You should do:

a.B["one"] = Type{
    A: Epyt{
        A: "test",
        B: "foo",
    },
    B: "something",
}
Edson Medina
  • 9,862
  • 3
  • 40
  • 51