对为什么在 Go 中 hashsum、encode、print 与 write、hashum、encode、print 不同感到困惑?

Confused about why hashsum, encode, print is different then write, hashum, encode, print in Go?

对不起标题。我想不出更好的方式来表达我的问题,如果其他人可以的话,我会很高兴地改变它。

Hasher 定义为

hasher := md5.New()

无论如何,我很好奇为什么会这样:

fmt.Println(hex.EncodeToString(hasher.Sum([]byte(input))))

给我 6869d41d8cd98f00b204e9800998ecf8427e,而这个:

hasher.Write([]byte(input))
fmt.Println(hex.EncodeToString(hasher.Sum(nil))

给我 49f68a5c8493ec2c0bf489821c21fc3b 还有这个:

fmt.Printf("%x\n", md5.Sum([]byte(input)))

给我 49f68a5c8493ec2c0bf489821c21fc3b。

通常hasher.Sum() 不会散列传递的切片。传递的切片用作 destination:它将当前散列附加到它并且不更改底层散列状态。 hasher.Write() 显然在哈希计算中包含了传递的切片。这两个例子根本不同,不同的结果不过是意料之中的。

始终阅读文档。 hash.Hash.Sum():

// Sum appends the current hash to b and returns the resulting slice.
// It does not change the underlying hash state.
Sum(b []byte) []byte

因此,当您第一次调用 hasher.Sum() 时,无论您传递给它什么,就结果哈希而言都无关紧要。如果您之前没有向 hasher 写入任何内容,您将看到初始哈希值。

当您下次调用 hasher.Write([]byte(input)) 时,您会将 input 的字节写入哈希器,因此当您接下来调用 hasher.Sum(nil) 时,您将看到计算的哈希值input。由于您传递 nil,因此将分配一个新的切片来容纳结果。

当您再次调用 hasher.Write([]byte(input)) 时,如前所述:这不会改变散列状态,传递的切片不用作输入,而仅用作“返回”结果的目的地,当前哈希值。因此,您将获得与从之前的 hasher.Sum(nil) 调用中获得的哈希值相同的哈希值。显然,如果传递的切片没有足够的容量来存储结果,则会分配/使用一个新的。

查看这个完整的、可运行的示例,它可以重现您的输出:

input := "hi"
hasher := md5.New()
fmt.Println(hex.EncodeToString(hasher.Sum([]byte(input))))

hasher.Write([]byte(input))
fmt.Println(hex.EncodeToString(hasher.Sum(nil)))

fmt.Printf("%x\n", md5.Sum([]byte(input)))

Go Playground 上试试。