英文:
Golang assignment of []map[string]struct error
问题
根据你提供的代码,我可以看出你正在处理一个项目,该项目从MongoDB中的数据创建CSV报告。在获取所需数据后,你需要将数据结构化为更合理的形式,而不是数据库中存在的混乱形式(这不是我的工作),并且几乎不可能以我需要的方式打印出来。对我来说,最合理的结构是一个切片(每个数据文档)的映射,将数据的名称映射到保存该名称数据的结构。然后,我只需循环遍历文档,并将值放入相应的结构中。
我的实现如下:
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))
// 设置值的方式如下
mongo_rows_struct[i][data_name].caution_note = fmt.Sprint(k)
// "i" 是文档索引,"k" 是要存储的数据
然而,这段代码不起作用。在运行go run
时,会返回./answerstest.go:140: cannot assign to mongo_rows_struct[i][data_name].caution_note
。我是Go的新手,不确定为什么不允许这样做。我确信这是一种无效的引用该特定数据位置的方式,如果在Go中甚至可以引用它的话。有没有其他方法可以实现这个设置行?如果按照我想要的方式实现这个过于复杂,我愿意使用其他类型的数据结构,并且对建议持开放态度。
英文:
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.
答案1
得分: 6
这是Golang的一个已知问题,被称为issue 3117。你可以使用一个临时变量来解决它:
var tmp = mongo_rows_struct[i][data_name]
tmp.caution_note = fmt.Sprint(k)
mongo_rows_struct[i][data_name] = tmp
英文:
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
答案2
得分: 0
根据我的理解,当你写下 mongo_rows_struct[i][data_name]
时,编译器会生成代码,该代码将返回 mongo_essential_data_t 结构体的副本(因为在 Go 中,结构体是值类型而不是引用类型),而 mongo_rows_struct[i][data_name].caution_note = fmt.Sprint(k)
将会在该副本上写入新的值。然后该副本将被丢弃。显然,这不是你期望的结果。因此,Go 编译器会生成错误以防止这种误解。
为了解决这个问题,你可以采取以下方法:
- 将数据类型的定义更改为
[]map[string]*mongo_essential_data_t
。 - 显式地创建结构体的副本,对该副本进行更改,并将其写回到映射中。
data := mongo_rows_struct[i][data_name] data.caution_note = fmt.Sprint(k) mongo_rows_struct[i][data_name] = data
当然,第一种解决方案更可取,因为它可以避免不必要的数据复制。
英文:
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:
- Change definition of your data type to
[]map[string]*mongo_essential_data_t
- 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论