正如您可能从以下代码中可以看出,我正在开发一个项目,该项目根据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))
//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
然而,这不起作用。在“开始运行”时,它返回./answerstest.go:140: cannot assign to mongo_rows_struct[i][data_name].caution_note
。我是Go的新手,不知道为什么我不允许这样做。我确定这是一种无效的方式来引用特定的数据位置,如果甚至可以在Go中引用它。完成此设置线的另一种方法是什么?如果以我想要的方式完成这项工作太多,我愿意使用不同类型的数据结构,并愿意接受建议。
答案 0 :(得分: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
答案 1 :(得分:0)
根据我的理解,当你写:
mongo_rows_struct[i][data_name]
编译器将生成代码,该代码将返回mongo_essential_data_t结构的副本(因为结构中的go是值类型,而不是引用类型),以及
mongo_rows_struct[i][data_name].caution_note = fmt.Sprint(k)
将为该副本写入新值。之后,副本将被丢弃。显然,它不是你所期望的。所以Go编译器生成错误以防止这种误解
为了解决这个问题,你可以:
1.将数据类型的定义更改为
[]map[string]*mongo_essential_data_t
2.明确创建结构的副本,在该副本中进行更改并将其写回地图
data := mongo_rows_struct[i][data_name]
data.caution_note = fmt.Sprint(k)
mongo_rows_struct[i][data_name] = data
当然,首选解决方案更可取,因为您可以避免不必要的数据复制