【问题标题】:Google Go Lang Assignment OrderGoogle Go Lang 作业顺序
【发布时间】:2012-08-07 20:14:07
【问题描述】:

我们来看下面的 Go 代码:

package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m map[string]Vertex

func main() {
    m = make(map[string]Vertex)
    m["Bell Labs"] = Vertex{
        40.68433, 74.39967,
    }
    m["test"] = Vertex{
        12.0, 100,
    }
    fmt.Println(m["Bell Labs"])
    fmt.Println(m)
}

它输出这个:

{40.68433 74.39967}

map[Bell Labs:{40.68433 74.39967} test:{12 100}]

但是,如果我更改测试顶点声明的 一个 次要部分,则将“}”向右移动 4 个空格,如下所示:

m["test"] = Vertex{
    12.0, 100,
}

.. 然后输出变为:

{40.68433 74.39967}

map[test:{12 100} Bell Labs:{40.68433 74.39967}]

为什么这么小的修改会影响我的地图顺序?

【问题讨论】:

  • 你确定这是什么原因造成的吗?两次运行未更改的程序时,您得到相同的顺序吗?

标签: go variable-assignment


【解决方案1】:

映射“顺序”取决于使用的散列函数。散列函数是随机的,以防止使用散列冲突的拒绝服务攻击。有关详细信息,请参阅问题跟踪器:

http://code.google.com/p/go/issues/detail?id=2630

根据规范不保证地图顺序。尽管在当前的 go 实现中没有这样做,但未来的实现可能会在 GC 或其他更改映射顺序的操作期间进行一些压缩,而无需您的代码修改映射。假设规范中未定义的属性是不明智的。

地图是一组无序元素的一种类型,称为元素类型,由另一种类型的一组唯一键索引,称为键类型。

【讨论】:

  • +1:比我的答案更精确的参考(来自 go 项目的问题)。
  • 非常感谢斯蒂芬。问题已关闭!
【解决方案2】:

地图不应总是以任何固定顺序打印其关键元素:
见“Go: what determines the iteration order for map keys?

但是,在最新的 Go 每周版本中(以及可能在本月发布的 Go1 中),迭代顺序是随机的(它从伪随机选择的键开始,哈希码计算以伪随机数)。
如果您使用每周版本(和 Go1)编译程序,每次运行程序时迭代顺序都会不同。

虽然 (Ref Map Type) 并没有完全像规范中那样拼写:

地图是一种无序组元素,称为元素类型,由另一种类型的唯一键集索引,称为键类型。

实际上,规格确实说明了这一点,但在For statement section

未指定映射的迭代顺序,也不保证从一次迭代到下一次迭代顺序相同

  • 如果在迭代过程中删除了尚未到达的映射条目,则不会产生相应的迭代值。
  • 如果在迭代期间插入映射条目,则行为取决于实现,但每个条目的迭代值最多会生成一次。
  • 如果map为nil,则迭代次数为0。

这是由code review 5285042 于 2011 年 10 月介绍的:

runtime: 地图迭代的随机偏移量


go-nuts thread 指出:

“它可以阻止人们做坏事”的原因似乎特别弱。
避免恶意哈希冲突更有意义
此外,指向代码的指针可以在开发过程中恢复该行为,以防出现难以解决的间歇性错误。

Patrick Mylund Nielsen 回复:

Dan 的注释实际上是 Python 开发人员不愿采用哈希 IV 随机化的主要论据——它破坏了他们的单元测试! PHP 最终选择完全不做,而是限制了http.Request 标头的大小,Oracle 等人根本不认为这是语言问题。
Perl 发现了这个问题并应用了一个类似于 Go 的修复程序,该修复程序包含在 2003 年的 Perl 5.8.1 中。
我可能错了,但我认为当这篇论文发表时,他们是唯一真正关心的人:“Denial of Service via Algorithmic Complexity Attacks”,攻击哈希表。


(最坏情况的哈希表冲突)

对于其他人来说,这在大约一年前变得非常流行,是一个很好的动力:
28c3: Effective Denial of Service attacks against web application platforms (YouTube video, December 2011)”,它显示了大多数流行的 web 执行中的常见缺陷 编程语言和平台(包括 PHP、ASP.NET、Java 等)可用于(ab)强制 Web 应用程序服务器在几分钟到几小时内为单个 HTTP 请求使用 99% 的 CPU。
这种攻击大多独立于底层 Web 应用程序,只是 依赖于 Web 应用程序服务器通常如何工作的一个共同事实。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 2021-05-23
    相关资源
    最近更新 更多