【问题标题】:Go: append directly to slice found in a mapGo:直接附加到在地图中找到的切片
【发布时间】:2017-09-29 15:34:45
【问题描述】:

我想创建一个切片映射,其中值附加到相应的切片。但是,当尝试直接附加到通过访问它返回的切片时(参见下面的评论),它不会被存储,所以我不得不使用长格式访问(评论下方的行)。

为什么会这样?我希望对地图的访问能够返回某种指针,所以在我看来mappedAminoAcid == aminoAcidsToCodons[aminoAcid];很明显,我错了。

谢谢!

aminoAcidsToCodons := map[rune][]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
    mappedAminoAcid, ok := aminoAcidsToCodons[aminoAcid]

    if ok {
        // NOT WORKING: mappedAminoAcid = append(mappedAminoAcid, codon)
        aminoAcidsToCodons[aminoAcid] = append(mappedAminoAcid, codon)
    } else {
        aminoAcidsToCodons[aminoAcid] = []string{codon}
    }
}

【问题讨论】:

  • 这就是 Go 的工作原理。您从地图索引操作中取回一个新切片。附加到这个切片确实附加到这个切片,并且不会做任何魔术,比如“我源于地图索引操作,所以让我们修改地图而不是我。”
  • 这很有趣,我认为切片基本上是指向数组的指针,所以我认为索引操作会返回指向该数组的指针。谢谢!
  • @jonathanGB:切片确实像指向数组的指针一样工作(切片头包含长度、容量和数组指针),但您希望它像指向数组指针的指针一样工作.
  • 切片本身是一个具有复制语义的普通值。它正在查看的支持数组是共享的。它可能在追加或不更新期间更新,具体取决于上限。
  • @jonathanGB:是的,但是数组指针也是该副本的一部分,因此如果需要重新分配数组,那也将有所不同。

标签: go


【解决方案1】:

append 如果底层数组必须增长以容纳新元素,则返回一个新切片。所以是的,您必须将新切片放回地图中。这与字符串的工作方式没有什么不同,例如:

var x map[string]string
x["a"] = "foo"

y := x["a"]
y = "bar"

// x["a"] is still "foo"

要获得您期望的行为,您必须使用切片指针。

aminoAcidsToCodons := map[rune]*[]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
    mappedAminoAcid := aminoAcidsToCodons[aminoAcid]
    *mappedAminoAcid = append(*mappedAminoAcid, codon)
}

话虽如此,由于nil 是追加的第一个参数,您可以将代码简化为

aminoAcidsToCodons := map[rune][]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
    aminoAcidsToCodons[aminoAcid] = append(aminoAcidsToCodons[aminoAcid], codon)
}

【讨论】:

  • 谢谢,解释得很好!
  • typed nil 适用于第一个参数,untyped nil 则不然。
猜你喜欢
  • 2018-12-05
  • 2020-07-09
  • 2021-09-21
  • 2017-09-22
  • 1970-01-01
  • 2016-06-04
  • 2019-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多