go中的切片迭代顺序

时间:2017-07-27 09:28:01

标签: go slice

好吧,我认为这可能是一个老问题,但我在堆栈溢出中找不到任何东西。在go中,不保证地图上的迭代顺序是可再现的。因此,建议的方法是将键保持在切片中并对该切片进行排序。然后迭代该切片以从地图中检索值,以便我们按顺序获取它们(因为由键组成的切片被排序,因此将以可重现的顺序排序)。所以这意味着需要对切片进行排序,否则切片上的迭代也不会给出可重现的顺序。但是当我在操场上尝试下面的代码时,我总是发现迭代中维护的顺序,然后在地图迭代的情况下,为什么需要对键片进行排序?

func main() {
    var mySlice = make([]string, 0)
    mySlice = append(mySlice, "abcd")
    mySlice = append(mySlice, "efgh")
    mySlice = append(mySlice, "ijkl")
    mySlice = append(mySlice, "mnop")
    mySlice = append(mySlice, "qrst")
    mySlice = append(mySlice, "uvwxyz")
    for _, val := range mySlice {
        fmt.Println(val)
    }
    fmt.Println(strings.Join(mySlice, "|"))

}

输出:

abcd
efgh
ijkl
mnop
qrst
uvwxyz
abcd|efgh|ijkl|mnop|qrst|uvwxyz

2 个答案:

答案 0 :(得分:6)

切片或数组将始终具有固定顺序,即它在内存中的布局方式。

您正在阅读的文档可能只是告诉您对切片进行排序,以便地图输出按排序顺序排列。

你是正确的,地图的迭代顺序是未定义的,因此每次执行时都可能不同。如果您使用切片迭代地图,那么它将始终以可靠的顺序返回,即切片中的键的顺序。

我建议您阅读有关slices的信息。

修改

如果有帮助,请考虑以下代码来说明切片的排序与其修复的顺序无关:

words := map[int]string{
    0: "hello",
    1: "there",
    2: "goodbye",
}
keys:=[]int{2,0,1}
for _, k := range keys {
    // Will output in order: Goodbye, hello, there
    fmt.Println("Key:", k, "Value:", words[k])
}

答案 1 :(得分:3)

切片排序的唯一原因是因为您要按已排序的顺序追加项目。如果您按照未按顺序添加项目

var mySlice = make([]string, 0)
mySlice = append(mySlice, "mnop")
mySlice = append(mySlice, "efgh")
mySlice = append(mySlice, "uvwxyz")
mySlice = append(mySlice, "ijkl")
mySlice = append(mySlice, "abcd")
mySlice = append(mySlice, "qrst")

(或通过从地图中拉出键来填充切片,这将是未排序的),然后迭代的顺序将是未排序的(一致,是,但始终未排序)。因此,如果您的目标是使用切片以排序顺序从地图中提取项目,则需要先对切片进行排序,除非您可以保证切片项目已按已排序的顺序插入。