在 Go 中迭代地图时修改地图

鉴于以下代码,我预计会出现无限循环,但循环在某个点停止。


m := make(map[int]string, 4)

m[0] = "Foo"

    

for k, v := range m {

    m[k+1] = v

}

我无法弄清楚引擎盖下发生了什么,因为不同的执行返回不同的输出。例如,这些是来自不同执行的几个输出:


map[0:Foo 1:Foo 2:Foo 3:Foo 4:Foo 5:Foo 6:Foo 7:Foo]

map[0:Foo 1:Foo]

map[0:Foo 1:Foo 2:Foo]

如何工作才能在特定点退出循环,退出条件是什么?range


开心每一天1111
浏览 88回答 3
3回答

蝴蝶刀刀

Spec:对于具有范围子句的语句,表示行为是不可预测的:未指定映射的迭代顺序,也不保证从一次迭代到下一次迭代相同。如果在迭代期间移除尚未到达的映射条目,则不会生成相应的迭代值。如果在迭代期间创建了映射条目,则该条目可能会在迭代期间生成,也可以跳过。对于创建的每个条目以及从一次迭代到下一次迭代,选择可能会有所不同。如果映射为 ,则迭代次数为 0。nil将元素添加到您正在测距的地图中,这些条目可能会被循环访问,也可能不会被循环访问,您不应该假设与此相关的任何事情。

明月笑刀无情

其他答案已经解释了您在代码段中观察到的行为。由于您的标题相当通用,但您的代码段仅涵盖在迭代地图时添加地图条目,因此这里有一个补充示例,应该说服您,在迭代地图时“交叉删除”地图条目是一个坏主意(Playground):package mainimport "fmt"func main() {    m := map[string]int{"foo": 0, "bar": 1, "baz": 2}    for k := range m {        if k == "foo" {            delete(m, "bar")        }        if k == "bar" {            delete(m, "foo")        }    }    fmt.Println(m)}该规范说:未指定映射的迭代顺序,也不保证从一次迭代到下一次迭代相同。如果在迭代期间移除尚未到达的映射条目,则不会生成相应的迭代值。结果,程序输出 或 ,但无法分辨哪个。map[bar:1 baz:2]map[baz:2 foo:0]

MMTTMM

基于语言规范:如果在迭代期间创建了映射条目,则该条目可能会在迭代期间生成,也可以跳过。因此,如果跳过新元素,for 循环最终会结束。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go