1

As you could probably tell from the below code I am working on a project which creates csv reports from data in mongoDB. After getting the data I need in, I need to structure the data into something more sensible then how it exists in the db, which is fairly horrendous (not my doing) and near impossible to print the way I need it. The structure that makes the most sense to me is a slice (for each document of data) of maps of the name of the data to a structure holding the data for that name. Then I would simply have to loop through the document and stuff values into the structs where they belong.

My implementation of this is

type mongo_essential_data_t struct {
        caution string
        citation string
        caution_note string
}

mongo_rows_struct := make([]map[string]mongo_essential_data_t, len(mongodata_rows))

//setting the values goes like this
mongo_rows_struct[i][data_name].caution_note = fmt.Sprint(k)
//"i" being the document, "k" being the data I want to store

This doesn't work however. When doing "go run" it returns ./answerstest.go:140: cannot assign to mongo_rows_struct[i][data_name].caution_note. I am new to Go and not sure why I am not allowed to do this. I'm sure this is an invalid way to reference that particular data location, if it is even possible to reference it in Go. What is another way to accomplish this setting line? If it is too much work to accomplish this the way I want, I am willing to use a different type of data structure and am open to suggestions.

2 Answers 2

6

This is a known issue of Golang, known as issue 3117. You can use a temporary variable to get around it:

var tmp = mongo_rows_struct[i][data_name]
tmp.caution_note = fmt.Sprint(k)
mongo_rows_struct[i][data_name] = tmp 
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for the response. Although, the program panics on the line mongo_rows_struct[i][data_name] = tmp. I have read around and had someone say that maps were immutable; is it possible to update the map once set?
Yes you can. What is the panic traceback?
panic: runtime error: assignment to entry in nil map goroutine 1 [running]: runtime.panic(0x59bc80, 0x7a373d) /home/user/src/go/src/pkg/runtime/panic.c:266 +0xb6 main.main() /home/user/go/src/mongotests/answerstest.go:148 +0x1cc0 With line 148 being the line above
Ok. For each of your i, you have to do this before trying to access elements of the map: mongo_rows_struct[i] = make(map[string]mongo_essential_data_t) Note that it has nothing to do with the issue, it is a Golang prerequisite when using maps.
Damn, how did I overlook that? Thank you for your solution though, it works perfectly now.
0

as per my understanding, when you write:
mongo_rows_struct[i][data_name]
compiler will generate code, which will return copy of mongo_essential_data_t struct(since struct in go is value type, not reference type), and
mongo_rows_struct[i][data_name].caution_note = fmt.Sprint(k)
will write new value to that copy. And after that copy will be discarded. Obviously, its not what you expect. So Go compiler generate error to prevent this misunderstanding.
In order to solve this problem you can:
1. Change definition of your data type to []map[string]*mongo_essential_data_t
2. Explicitly create copy of your struct, make changes in that copy and write it back to the map
data := mongo_rows_struct[i][data_name]
data.caution_note = fmt.Sprint(k)
mongo_rows_struct[i][data_name] = data

Of course, first solution is preferable because you will avoid unnecessary copying of data

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.