为什么说Go的Map是无序的?

Go源码版本1.13.8

系列导读

本系列基于64位平台、1Page=8KB

前言

是的,我也是一个PHPer,对于我们PHPer转Gopher的银????,一定有个困扰:Go语言里每次遍历Map输出元素的顺序并不一致,但是在PHP里却是稳定的。今天我们就来看看这个现象的原因。

本文目录如下:

  • Go的Map遍历结果“无序”

    • 遍历Map的索引的起点是随机的

  • Go的Map本质上是“无序的”

    • 无序写入

      • 正常写入(非哈希冲突写入)

      • 哈希冲突写入

    • 扩容

      • 成倍扩容迫使元素顺序变化

      • 等量扩容

Go的Map遍历结果“无序”

现象:Go语言里每次遍历Map输出元素的顺序并不一致,但是在PHP里却是稳定的。

关于这个现象我就不过多赘述了,同时我相信大家应该都网上搜过相关的文章,这些文章大多都说明了原因:For ... Range ... 遍历Map的索引的起点是随机的,没错,就是下面这段代码。

// versions/1.13.8/src/cmd/compile/internal/gc/range.go
func walkrange(n *Node) *Node {
	
    // 略...

    // 遍历Map时
	case TMAP:
		
        // 略...

        // 调用mapiterinit mapiterinit函数见下方
		fn := syslook("mapiterinit")

		// 略...

		fn = syslook("mapiternext")
		
        // 略...
}

// versions/1.13.8/src/runtime/map.go
func mapiterinit(t *maptype, h *hmap, it *hiter) {

    // 略...

    // 对,就是这行代码
    // 随机一个索引值,作为遍历开始的地方
	// decide where to start
	r := uintptr(fastrand())
	if h.B > 31-bucketCntBits {
		r += uintptr(fastrand()) << 31
	}
	
    // 略...

	mapiternext(it)
}

但是呢,有没有再推测过Go的作者们这么做背后的真正原因是什么?个人觉着因为:

Go的Map本质上是“无序的”

Go的Map本质上是“无序的”,为什么这么说?

“无序”写入

1. 正常写入(非哈希冲突写入):是hash到

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值