【问题标题】:Golang assignment of []map[string]struct error[]map[string]struct 的 Golang 赋值错误
【发布时间】:2014-08-04 23:24:09
【问题描述】:

您可能从下面的代码中可以看出,我正在开发一个从 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 中引用它的话。完成此设置线的另一种方法是什么?如果按照我想要的方式完成这项工作太多,我愿意使用不同类型的数据结构并愿意接受建议。

【问题讨论】:

    标签: data-structures struct go maps variable-assignment


    【解决方案1】:

    这是 Golang 的一个已知问题,称为 issue 3117。您可以使用临时变量来解决它:

    var tmp = mongo_rows_struct[i][data_name]
    tmp.caution_note = fmt.Sprint(k)
    mongo_rows_struct[i][data_name] = tmp 
    

    【讨论】:

    • 感谢您的回复。虽然,程序在mongo_rows_struct[i][data_name] = tmp 行出现了恐慌。我已经阅读并有人说地图是不可变的;设置后是否可以更新地图?
    • 是的,你可以。什么是恐慌回溯?
    • panic:运行时错误:分配给 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 第148行是上面的行
    • 好的。对于您的每个i,您必须在尝试访问地图元素之前执行此操作:mongo_rows_struct[i] = make(map[string]mongo_essential_data_t) 请注意,这与问题无关,这是使用地图时的 Golang 先决条件。
    • 该死,我怎么忽略了这一点?不过,感谢您的解决方案,它现在可以正常工作了。
    【解决方案2】:

    据我了解,当您写信时:
    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

    当然,第一个解决方案更可取,因为您将避免不必要的数据复制

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-08
      • 2021-08-09
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      • 2020-09-22
      • 2022-11-22
      相关资源
      最近更新 更多