[]byte(s)是最直接、安全的utf-8字符串转字节数组方式,但仅适用于utf-8字节展开;若需gbk等字符集转换,必须用golang.org/x/text/encoding,不可强转或unsafe。

[]byte(s) 是最直接、安全、符合 Go 语义的字符串转字节数组方式,但仅适用于 UTF-8 字节展开;若需字符集转换(如 GBK、Shift-JIS),必须用 golang.org/x/text/encoding,不能靠类型强制或 unsafe。
string 转 []byte:别碰 unsafe,也别默认可修改
绝大多数场景下,[]byte(s) 就是你要的转换。它不分配新内存,只复用底层字节序列 —— 这是高效的设计,但也是陷阱来源:
- 如果你后续对得到的
[]byte做写操作(比如b[0] = 'X'),会破坏原字符串的只读性(Go 不禁止,但违反语言契约) - 需要可修改副本?用
append([]byte(nil), s...)或copy(make([]byte, len(s)), s) -
unsafe方式(如*(*[]byte)(unsafe.Pointer(&s)))在 Go 1.22+ 已不可靠,运行时可能 panic 或返回错误长度,且无法通过 vet 检查
GBK / Big5 / Shift-JIS 等非 UTF-8 字符集转换
Go 的 string 内部永远是 UTF-8,所以“把字符串转成 GBK 字节数组”本质是:UTF-8 → Unicode 码点 → GBK 字节。这必须经过编码器,不能跳步:
- 导入对应包,例如 GBK:
"golang.org/x/text/encoding/simplifiedchinese" - 创建编码器:
encoder := simplifiedchinese.GBK.NewEncoder() - 调用
transform.String(encoder, s)得到 GBK 编码后的字符串,再用[]byte(...)展开为字节数组 - 注意错误处理:
transform.String可能返回transform.ErrShortDst或transform.ErrInvalidUTF8,后者说明输入含非法 UTF-8 序列(比如原始数据本就是乱码 GBK 字节被误当 string)
十六进制字符串(如 "48656c6c6f")转 []byte
这不是字符集问题,而是解析需求。常见于协议字段、密钥、调试输出等:
- 标准库有现成方案:
hex.DecodeString(s)(来自encoding/hex),要求输入是纯十六进制字符(0–9, a–f, A–F),长度为偶数 - 若字符串含前缀如
"0x4865..."或转义格式如"\x48\x65",需先清洗或换用正则 +strconv.ParseUint(..., 16, 8) - 错误处理不可省:
hex.DecodeString返回nil, error,常见错误是encoding/hex: invalid byte
interface{} 或结构体转 []byte:别强转,选序列化
试图写 []byte(v)(其中 v interface{})会编译失败。因为 interface{} 没有固定内存布局:
- 要跨语言、保结构:用
json.Marshal(v),但不支持func、chan、循环引用 - 要体积小、速度快、同 Go 生态:用
encoding/gob,但输出含类型信息,不可读、不可跨语言 - 要二进制紧凑、字段可控:用
encoding/binary+struct{ X uint32; Y int16 },但必须提前知道结构,且字段需导出 - 绝对不要用
unsafe强制解释interface{}内存 —— 其内部表示从 Go 1.17 起已变更,现在是 2 个 word,未来随时可能再变
真正容易被忽略的点是:所有“字符串转字节”的需求,必须先分清你到底要什么——是取 UTF-8 字节快照?还是做字符集编码转换?还是解析某种文本编码格式? 混淆这三者,就会在测试环境正常、上线后乱码,或在不同 Go 版本间突然崩溃。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











