当前位置:首页 > 文章列表 > Golang > Go教程 > Go encoding/hex Encoder 怎样把二进制流连续写成十六进制文本

Go encoding/hex Encoder 怎样把二进制流连续写成十六进制文本

来源:17golang原创 2026-10-24 13:30:39 0浏览 收藏

如果二进制数据不是一次性放在内存里,而是分几次从网络、文件或协议帧写出,encoding/hex.NewEncoder 更合适:它返回一个 io.Writer,每次收到源字节就转成小写十六进制字符并写给下游 Writer。这样可以把“读取分片”和“生成文本”连接起来,不需要先拼成一个大切片。

官方文档:https://pkg.go.dev/encoding/hex@go1.27.3#NewEncoder

要点速览
  • hex.NewEncoder(dst) 的职责是编码并转写,返回值按 io.Writer 使用。
  • 连续调用 Write 会连续产生十六进制文本;每个源字节对应两个小写字符。
  • Write 返回的 n 是已消费的源字节数,错误来自下游 Writer,要立即处理。

先把 Encoder 放在正确的边界上

NewEncoder 接收一个目标 io.Writer,例如 bytes.Buffer、文件或网络响应。它返回的仍然是 Writer,因此调用方只需要持续写入原始字节;编码器内部会把数据转成小写十六进制字符。这个 API 适合持续输出,不适合拿来反向解码,也不负责校验文件内容。

实现上,标准库会把输入分块编码后写给下游;官方源码中的内部缓冲区大小为 1024 个十六进制字符,调用方不应把这个实现细节当成接口承诺。真正需要关注的是:下游写失败后,后续写入会沿用这个错误,不能继续假装输出完整。

Go encoding/hex Encoder 将分片字节、编码器和下游 Writer 连接成连续十六进制文本的结构说明图
图1:结构说明图,展示分片字节进入 hex Encoder 后写入下游 Writer 的静态关系,不是运行截图。

用一个小工具连续写入多个分片

下面的小程序把两个分片写进同一个编码器,再从缓冲区取回结果。第二次写入不会覆盖第一次结果,而是从上次结束的位置继续追加,因此输出可以对应连续的协议片段或日志块。

package main

import (
    "bytes"
    "fmt"
    "encoding/hex"
)

func encodeChunks(chunks ...[]byte) (string, error) {
    var dst bytes.Buffer
    encoder := hex.NewEncoder(&dst)

    for _, chunk := range chunks {
        // 每个分片都写入同一个 Encoder,编码结果会自然连续。
        if _, err := encoder.Write(chunk); err != nil {
            // 下游 Writer 出错时立即返回,避免把不完整文本当成成功结果。
            return "", err
        }
    }
    return dst.String(), nil
}

func main() {
    // 分片可以来自不同读取动作,这里只用两个字节切片演示边界。
    text, err := encodeChunks([]byte{0x48, 0x69}, []byte{0x21})
    if err != nil {
        // 示例程序把错误直接打印出来;服务代码应按业务记录或返回。
        panic(err)
    }
    fmt.Println(text) // 输出 486921
}

这里的 bytes.Buffer 只是内存中的下游 Writer;换成打开的文件或实现了 io.Writer 的网络对象,调用方式不变。由于编码结果长度是源数据的两倍,示例中的三个源字节最终得到六个十六进制字符。

分片写入时要看懂 n 和 err

很多代码只检查 err,却忽略了 n 的含义。对于 hex.NewEncoder 返回的 Writer,n 表示已经从本次输入切片中消费的源字节数量,不是已经写出的十六进制字符数量。若下游 Writer 只写出一部分并返回错误,编码器会把下游错误保留下来,调用方应停止继续发送。

func writeChunks(dst io.Writer, chunks [][]byte) error {
    encoder := hex.NewEncoder(dst)
    for _, chunk := range chunks {
        // n 按源字节计算;不要用 n 直接当作十六进制字符串长度。
        n, err := encoder.Write(chunk)
        if err != nil {
            // 记录当前分片和底层错误,调用方才能决定重试或终止。
            return fmt.Errorf("写入十六进制分片失败,已消费 %d 个源字节: %w", n, err)
        }
        if n != len(chunk) {
            // 正常的完整 Writer 应消费整个分片,短写无错误也不能静默忽略。
            return fmt.Errorf("十六进制分片短写:%d/%d", n, len(chunk))
        }
    }
    return nil
}

这个函数需要补充 fmt、io 和 encoding/hex 的导入。示例刻意把错误上下文放在调用处,方便把失败定位到具体分片;不要把一次失败后的编码器当成可恢复的全新 Writer 使用。

Go hex Encoder Write 返回源字节计数并传播下游错误的边界说明图
图2:边界说明图,展示 Write 的源字节计数、下游错误和完整分片之间的静态关系,不是运行证据。

什么时候改用一次性编码 API

如果数据已经完整存在于一个切片中,hex.EncodeToString 更直接;如果要把结果追加到已有切片,可以使用 hex.AppendEncode。只有当输入会分段到达,或目标本身就是一个持续写入的 Writer 时,NewEncoder 才能体现它的边界优势。

场景更合适的选择原因
一次性字节切片hex.EncodeToString表达简单,直接得到字符串
追加到已有切片hex.AppendEncode由调用方管理目标切片
多个分片持续写出hex.NewEncoder保持 Writer 链,不必先合并输入
需要 hexdump 格式hex.Dumper输出带偏移和可打印区域的转储格式

常见问题

NewEncoder 输出大写十六进制吗?

不会。标准库文档说明它写出小写十六进制字符;如果协议要求大写,需要在边界处另行转换或选择能满足协议格式的编码方案。

每个分片之间会自动加空格或换行吗?

不会。多个 Write 的结果会直接连接。分隔符属于协议或日志格式的一部分,应由调用方明确写入,不能期待编码器自动插入。

写入失败后可以继续调用 Write 吗?

不建议。编码器会记住下游错误,后续写入不会恢复一个已经失败的输出链;应保留原始错误并结束这次编码任务。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go bytes.FieldsFuncSeq 怎样按函数规则惰性遍历字段Go bytes.FieldsFuncSeq 怎样按函数规则惰性遍历字段
上一篇
Go bytes.FieldsFuncSeq 怎样按函数规则惰性遍历字段
Go http.Request.Write 怎样把请求写成 HTTP 报文
下一篇
Go http.Request.Write 怎样把请求写成 HTTP 报文
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    647次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    675次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    721次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    680次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    514次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码