登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  Golang >  Go教程

Go crypto/sha256 New 和 Sum256 怎么选

来源:17golang原创

时间:2026-09-15 14:28:50 247浏览 收藏

在 Go 里计算一段数据的 SHA-256,最容易遇到的选择就是 sha256.New()sha256.Sum256()。结论很直接:数据已经完整放在 []byte 中,而且只计算一次,优先用 Sum256;数据来自文件、网络或分块读取,需要持续写入时,用 New

要点速览
  • Sum256(data) 一次接收完整数据,返回固定类型 [32]byte
  • New() 返回 hash.Hash,可以多次 Write,适合流式输入。
  • 两条路径对同一字节序列得到相同摘要,但输入边界和结果类型不同。

先看输入:一次性字节还是持续数据流

Sum256 的参数是完整的 []byte。配置项、短字符串、请求体已经读入内存时,直接调用最清楚;返回值是长度为 32 的数组,打印或比较时可以直接使用。

New 返回一个实现了 hash.Hash 的摘要对象。它不要求一开始就拥有全部数据,可以边读边写,因而不会为了调用摘要函数而额外拼出一个完整的大切片。

Go crypto/sha256 中一次性 []byte 选择 Sum256、持续数据流选择 New 的输入分流结构图
图1:sha256.New 与 sha256.Sum256 的输入选择说明图,不是运行截图或执行证据。

两种写法的返回类型并不相同

先看最小示例。示例中的注释说明了关键类型,输出使用十六进制只是为了便于阅读,并没有改变摘要本身。

package main

import (
	"crypto/sha256"
	"fmt"
)

func main() {
	data := []byte("go digest")

	// Sum256 一次处理完整字节切片,结果是 [32]byte。
	fixed := sha256.Sum256(data)
	fmt.Printf("sum256=%x\n", fixed)

	// New 返回 hash.Hash;Write 可以在多个阶段持续接收数据。
	h := sha256.New()
	_, _ = h.Write([]byte("go ")) // 这里写入第一段数据。
	_, _ = h.Write([]byte("digest")) // 这里写入第二段数据。
	streamed := h.Sum(nil) // Sum(nil) 取出当前摘要字节,不负责重新计算输入。
	fmt.Printf("new=%x\n", streamed)
}

两行输出的摘要应当一致,因为两次调用接收的字节顺序都是 go digest。差异在于:fixed 是数组,streamed 是字节切片;前者适合直接作为值传递,后者更适合接到编码、写文件或网络响应的后续流程。

New 的关键是 Write 与 Sum 的两段式流程

处理文件时,通常让 io.Copy 把读取到的数据直接写入摘要对象。这里要检查打开文件和复制过程的错误;defer f.Close() 只负责释放文件描述符,不能代替 io.Copy 的错误处理。

import (
	"crypto/sha256"
	"io"
	"os"
)

func fileSHA256(path string) ([]byte, error) {
	// 打开文件后及时安排关闭,避免异常返回时泄漏文件描述符。
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	// io.Copy 让文件按流写入 hash.Hash,不需要把整个文件读进内存。
	h := sha256.New()
	if _, err := io.Copy(h, f); err != nil {
		return nil, err
	}
	// Sum(nil) 返回当前累计状态的摘要字节,传 nil 表示不追加到已有切片。
	return h.Sum(nil), nil
}

这段函数需要补齐 crypto/sha256ioos 导入。实际项目里,如果读取器本身可能返回错误,仍然应该把错误向上返回,而不是只看最终摘要。

Go hash.Hash 通过 Write 累计状态并由 Sum(nil) 输出摘要字节的结果类型边界图
图2:hash.Hash 累计状态与摘要结果的边界说明图,不是运行截图或执行证据。

按这张清单决定用哪个 API

场景建议原因
短字符串、完整请求体、已存在的 []bytesha256.Sum256代码短,返回 [32]byte,比较直观
大文件、网络响应、分块上传sha256.New多次 Write,不必集中保存全部输入
需要复用摘要对象处理新的独立输入重新调用 New每个摘要应有独立累计状态
需要字符串展示fmt.Sprintf("%x", sum)十六进制是展示格式,不是新的摘要算法

还有一个容易混淆的边界:SHA-256 是摘要,不是加密。摘要不能靠“解密”恢复原文;如果场景是密码存储、消息认证或数字签名,还需要按具体威胁模型选择专用方案,不能只因为能得到一串十六进制字符就认为完成了安全设计。

常见问题

sha256.New 和 sha256.Sum256 算出来的值一样吗?

只要输入字节完全相同、顺序也相同,摘要值一样。区别主要是输入方式和返回类型,不是算法不同。

为什么不能把文件直接传给 Sum256?

Sum256 只接收 []byte。文件应通过 New 配合 io.Copy 或循环 Write 处理,避免一次性加载整个文件。

h.Sum(nil) 会清空 hash.Hash 吗?

不要把 Sum(nil) 当成清空操作。它读取当前累计状态并返回摘要;如果要处理另一份独立数据,直接新建一个 sha256.New() 更容易表达边界。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>