我有一个导航栏作为地图:
var navbar = map[string]navbarTab{
}
Run Code Online (Sandbox Code Playgroud)
哪里navbarTab
有各种属性,儿童用品等.当我尝试渲染导航栏(带for tabKey := range navbar
)时,它以随机顺序显示.我知道range
它在运行时会随机排序,但似乎无法获得有序的键列表或迭代插入顺序.
游乐场链接在这里:http://play.golang.org/p/nSL1zhadg5虽然它似乎没有表现出相同的行为.
如何在不破坏插入顺序的情况下迭代此地图?
在围棋编程语言规范说:
3.未指定地图上的迭代顺序.[...]
这是可以预料到的,因为地图类型可以实现为哈希表,搜索树或其他数据结构.但是如何map
在Go中实际实现?
换句话说,决定键的迭代顺序的是什么
for k, _ := range m { fmt.Println(k) }
Run Code Online (Sandbox Code Playgroud)
在我看到带string
键的地图显然确实有一定的迭代顺序后,我开始对此感到好奇.像这样的程序
package main
import ("fmt"; "time"; "rand")
func main() {
rand.Seed(time.Seconds())
words := [...]string{"foo", "bar", "a", "b", "c", "hello", "world",
"0", "1", "10", "100", "123"}
stringMap := make(map[string]byte)
for i := range rand.Perm(len(words)) {
stringMap[words[i]] = byte(rand.Int())
}
fmt.Print("stringMap keys:")
for k, _ := range stringMap { fmt.Print(" ", k) }
fmt.Println()
}
Run Code Online (Sandbox Code Playgroud)
在我的机器上打印以下内容:
stringMap keys: a c b …
Run Code Online (Sandbox Code Playgroud) 最近我参加了几次围棋面试.第一个问我How is channel implemented?
,然后第二个问我How is goroutine implemented?
.你可以猜到,下一个问道How is a Go interface implemented?
.
我一直在使用Go六个月,但说实话,我从来没有关心或知道这些Go internals
.
我试着通过阅读Go的源代码来学习这些,但却无法真正理解这些精髓.
所以问题是,对于Go中的菜鸟,我如何学习Go internals?
我正在寻找一种确定Go
map
的有序范围.
Golang规范说明如下:
未指定地图上的迭代顺序,并且不保证从一次迭代到下一次迭代是相同的.如果在迭代期间删除了尚未到达的映射条目,则不会生成相应的迭代值.如果在迭代期间创建了映射条目,则可以在迭代期间生成该条目,或者可以跳过该条目.对于创建的每个条目以及从一次迭代到下一次迭代,选择可能不同.如果映射为nil,则迭代次数为0.
我在StackOverflow和Google上找到的所有内容都是(imho)我不喜欢的解决方法.
有没有一种可靠的方法来迭代地图并按照它们插入的顺序检索项目?
我发现的解决方案是:
在两个单独的切片中跟踪键和值:听起来像"不要使用地图",失去了使用地图的所有优点.
使用映射但跟踪不同切片中的密钥:这意味着数据重复可能导致数据不对齐,并最终可能带来大量错误和痛苦的调试.
你有什么建议?
编辑以响应可能的重复标记.
我的问题和提供的问题(这个问题,但也是这个问题)之间存在细微的差别,这两个问题都要求在按键字典顺序之后循环遍历地图; 相反,我特别问过:
有没有一种可靠的方法来迭代地图并按照它们插入的顺序检索项目?
这不是词典,因此不同于@gramme.ninja
问题:
如何让键按顺序/排序地图,以便键按顺序排列并且值对应?
从Golang 源代码看,它们似乎遵循哈希表(即存储桶数组)的相当标准的实现。基于此,对于不变的映射,迭代应该是确定性的(即按顺序迭代数组,然后按顺序在存储桶中迭代)。他们为什么要使迭代是随机的?