
本文旨在解决go语言中测试返回`[]byte`类型哈希值时常见的比较错误。核心问题在于将原始字节哈希与十六进制字符串哈希进行不当比较。教程将详细阐述如何通过`fmt.sprintf`将原始字节哈希转换为十六进制字符串,从而实现准确、可靠的测试,并提供示例代码和最佳实践。
在Go语言中进行单元测试是保证代码质量的重要环节。当函数返回类型为[]byte,特别是加密哈希值时,初学者常会遇到比较上的困惑。本教程将深入探讨如何正确测试返回原始字节哈希的函数,避免常见的比较错误。
我们首先定义一个简单的哈希函数,它接收一个字符串并返回其MD5哈希值的[]byte表示:
package main
import (
"crypto/md5"
"io"
)
// myHash 计算给定字符串的MD5哈希值,并以 []byte 形式返回。
func myHash(s string) []byte {
h := md5.New()
io.WriteString(h, s)
return h.Sum(nil) // h.Sum(nil) 返回一个 [16]byte 数组,此处隐式转换为 []byte
}myHash函数内部使用了crypto/md5包,h.Sum(nil)方法返回的是一个[16]byte类型的数组,代表了MD5哈希的原始字节序列。例如,字符串"linux"的MD5哈希值在原始字节层面是[226 6 165 78 151 105 12 206 80 204 135 45 221 14 232 150]。而我们通常看到的"e206a54e97690cce50cc872dd70ee896"是这个原始字节序列的十六进制字符串表示。
在测试返回[]byte哈希值的函数时,一个常见的错误是将原始字节哈希与十六进制字符串表示进行不当比较。考虑以下错误的测试代码:
立即学习“go语言免费学习笔记(深入)”;
package main
import (
"bytes"
"testing"
)
func TestMyHashIncorrect(t *testing.T) {
s := "linux"
// 预期值是一个十六进制字符串
bf := "e206a54e97690cce50cc872dd70ee896"
x := myHash(s) // x 是 []byte 类型的原始哈希值
// 错误:将十六进制字符串转换为 []byte 后进行比较
// []byte(bf) 会将字符串 "e206a54e97690cce50cc872dd70ee896" 中的每个字符
// 转换为其对应的ASCII/UTF-8字节,而不是将其解析为原始的MD5字节序列。
// 例如,'e' 的字节值是 101,'2' 的字节值是 50,这与原始MD5字节完全不同。
if !bytes.Equal(x, []byte(bf)) {
t.Errorf("TestMyHash for %q failed. Got %v, want %v", s, x, []byte(bf))
}
}上述测试代码会始终失败。原因在于[]byte(bf)的操作。当我们将一个十六进制字符串(如"e206a54e97690cce50cc872dd70ee896")强制转换为[]byte时,Go语言并不会将其解析为对应的原始字节序列。相反,它会将字符串中的每个字符(例如'e', '2', '0', '6'等)的ASCII/UTF-8编码值作为字节放入切片。这与myHash函数返回的原始MD5字节序列是完全不同的,因此bytes.Equal函数永远返回false。
要正确比较哈希值,关键在于确保比较的两个值具有相同的表示形式。最常见和推荐的方法是将[]byte类型的原始哈希值转换为其十六进制字符串表示,然后与预期的十六进制字符串进行比较。Go语言的fmt.Sprintf函数提供了强大的格式化能力,可以轻松实现这一点。
使用%x格式化动词可以将字节切片格式化为小写十六进制字符串。
package main
import (
"fmt"
"testing"
)
// TestMyHashCorrect 演示了如何正确测试返回 []byte 哈希值的函数。
func TestMyHashCorrect(t *testing.T) {
tests := []struct {
input string
want string // 预期值现在是十六进制字符串
}{
{
input: "linux",
want: "e206a54e97690cce50cc872dd70ee896", // "linux" 的MD5哈希
},
{
input: "golang",
want: "b506636756c9e03403565e236592231b", // "golang" 的MD5哈希
},
{
input: "", // 空字符串的MD5哈希
want: "d41d8cd98f00b204e9800998ecf8427e",
},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("input=%s", tt.input), func(t *testing.T) {
gotBytes := myHash(tt.input)
// 核心:将 []byte 原始哈希值转换为十六进制字符串进行比较
gotString := fmt.Sprintf("%x", gotBytes)
if gotString != tt.want {
t.Errorf("myHash(%q) got %q, want %q", tt.input, gotString, tt.want)
}
})
}
}在这个修正后的测试中:
如果需要大写十六进制表示,可以使用%X格式化动词。
在Go语言中测试返回[]byte类型哈希值的函数时,核心在于理解原始字节表示与十六进制字符串表示之间的区别。避免将十六进制字符串直接转换为[]byte进行比较的错误做法。正确的测试方法是利用fmt.Sprintf("%x", ...)将原始字节哈希格式化为十六进制字符串,然后与预期的十六进制字符串进行对比。遵循这些指导原则和最佳实践,可以确保你的哈希函数测试既准确又健壮。
以上就是Go语言中正确测试哈希函数返回值的方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号