当前位置:首页 > 文章列表 > Golang > Go问答 > Go Base64 标准编码和 RawStdEncoding 有什么区别

Go Base64 标准编码和 RawStdEncoding 有什么区别

来源:17golang原创 2026-11-11 00:16:59 0浏览 收藏

Go 的 base64.StdEncoding 和 base64.RawStdEncoding 使用同一套标准 Base64 字母表,真正的区别是末尾是否保留 = 填充。需要和已有协议、签名格式或其他语言实现互通时,先确认对方是否允许填充,再让编码端和解码端成对选择;不要把 Raw 误解成 URL 安全编码。

要点速览
  • StdEncoding 使用标准填充字符 =,输出长度通常是 4 的倍数。
  • RawStdEncoding 只取消填充,字母表仍是标准字母表,+ 和 / 的语义没有变化。
  • 协议两端必须共享同一个约定;字段只允许无填充时选 Raw,兼容 RFC 4648 标准形式时优先选 Std。

先看清两种编码真正差在哪里

把同一段字节交给两个编码器,最容易看出区别。下面的例子选择长度不是 3 的倍数的输入,这样标准编码会出现填充,而 Raw 变体会省略它:

package main

import (
    "encoding/base64"
    "fmt"
)

func main() {
    input := []byte("Go")

    // 两个编码器使用同一套标准 Base64 字母表,只比较填充策略。
    standard := base64.StdEncoding.EncodeToString(input)
    raw := base64.RawStdEncoding.EncodeToString(input)

    fmt.Println(standard) // R28=
    fmt.Println(raw)      // R28
}
Go StdEncoding 与 RawStdEncoding 对同一段字节保留或去掉等号填充的结构说明图
图1:Base64 标准编码与 RawStdEncoding 的填充差异说明图,不是运行截图。

StdEncoding 的输出是 R28=,最后的等号用于把编码结果补齐到完整的 4 字符分组;RawStdEncoding 输出 R28,只省略这个填充字符。输入长度恰好是 3 的倍数时,两者可能看起来完全一样,所以不要用单个“无等号”的样例判断编码器。

标准字母表和 Raw 变体不要混为一谈

Base64 里有两个经常被同时讨论、但职责不同的选择:一是使用哪套 64 字符字母表,二是是否使用填充。StdEncoding 与 RawStdEncoding 都属于标准字母表;后者可以理解为标准编码的 NoPadding 版本。

编码器字母表填充常见约束
StdEncoding标准 Base64保留 =对接明确要求标准填充的协议或已有实现
RawStdEncoding标准 Base64不保留字段约定无填充,或长度希望更短
URLEncodingURL 安全字母表保留 =需要 URL 查询参数或路径安全字符时
RawURLEncodingURL 安全字母表不保留URL 安全且无填充的字段

本文只讨论前两行。若问题是“Base64 放进 URL 后出现 +、/ 或转义问题”,应另看 URL 安全字母表,不要只把 StdEncoding 换成 RawStdEncoding。

按协议约束选择编码器

选择时先问三个问题:对方是否明确要求 =;字段是否有固定长度或长度预算;对接方能否使用同样的解码器。只要协议文档给出一种形式,就以协议为准,不要因为 Raw 输出更短就自行切换。

package main

import (
    "encoding/base64"
    "fmt"
)

func encodeToken(raw []byte, withoutPadding bool) string {
    // 无填充只能在协议允许时启用,否则会改变线上字段格式。
    enc := base64.StdEncoding
    if withoutPadding {
        enc = base64.RawStdEncoding
    }
    return enc.EncodeToString(raw)
}

func main() {
    token := []byte("user-42")
    fmt.Println(encodeToken(token, false)) // 标准形式,可能带 '='
    fmt.Println(encodeToken(token, true))  // Raw 形式,不带 '='
}

对于签名输入、缓存键和短令牌,编码结果本身常常会参与哈希或拼接。此时多一个 = 不只是显示差异,而是会改变待签名字符串;编码策略必须在协议层固定,并在文档中写清“标准填充”还是“无填充”。

编码端和解码端必须成对选择

编码端使用哪种形式,解码端就应该使用对应的 Encoding。不要先用字符串裁剪去掉等号,再交给标准解码器;也不要把收到的无填充字段无条件补等号,因为你可能会掩盖协议双方配置不一致的问题。

package main

import (
    "encoding/base64"
    "fmt"
)

func decodeToken(value string, withoutPadding bool) ([]byte, error) {
    // 解码器与编码器保持同一填充约定,错误交给调用方处理。
    enc := base64.StdEncoding
    if withoutPadding {
        enc = base64.RawStdEncoding
    }
    decoded, err := enc.DecodeString(value)
    if err != nil {
        return nil, fmt.Errorf("base64 解码失败: %w", err)
    }
    return decoded, nil
}
Go Base64 协议字段中编码端与解码端按相同填充约定配对的结构说明图
图2:编码端与解码端按填充约定配对的结构说明图,不是运行截图。

如果服务端返回带 = 的值,而客户端固定用 RawStdEncoding 解码,或者反过来,通常会得到格式错误。排查时先把原始传输值完整记录为安全的可复现样本,再确认两端的编码器名称、是否做过字符串裁剪,以及协议是否允许两种形式同时存在。

什么时候选 Std,什么时候选 Raw

可以把选择规则收敛成一张小表:

场景推荐原因
新协议没有特别限制StdEncoding标准形式更容易和默认实现互通
协议明确规定无填充RawStdEncoding直接表达无填充约定,避免手工裁剪
对接方只给出一个固定解码器跟随对方兼容性优先于本地输出长度
问题涉及 URL 字符另选 URL 变体填充策略和字母表是两个独立维度

最稳妥的工程做法是把编码器作为协议适配层的一部分,不在业务代码中到处直接调用全局变量;同时为带填充和无填充各保留一个明确的测试样例,覆盖输入长度不是 3 的倍数的情况。

常见问题

RawStdEncoding 会把 + 和 / 换掉吗?

不会。它只取消标准 Base64 的末尾填充,仍然使用标准字母表。如果还需要 URL 安全字符,应考虑 RawURLEncoding。

为什么我的测试里两个编码结果一样?

当输入字节数恰好是 3 的倍数时,标准编码不需要补 =,两者自然相同。测试时可以加入长度为 1、2、4 或 5 的输入。

能不能把等号删掉再用 StdEncoding 解码?

不建议。应该按协议直接使用对应的 Raw 解码器;手工删改会让格式约定散落在调用方,也可能使另一端无法判断真实编码形式。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go base64.Strict 怎么拒绝非零填充位的编码输入Go base64.Strict 怎么拒绝非零填充位的编码输入
上一篇
Go base64.Strict 怎么拒绝非零填充位的编码输入
Go base64.Decode 返回 n 和错误时怎么处理已写入字节
下一篇
Go base64.Decode 返回 n 和错误时怎么处理已写入字节
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    972次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    980次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1093次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1064次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    903次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码