Go中的编码转换
qingheluo2025-03-07清河洛79
在使用Go处理文本(如网页)时,会遇到编码问题,Go的默认编码是UTF-8,遇到其他编码的字符会出错,此时需要对文本进行转换在Go的官方库中没有编码转换相关库,但是在golang.org/x中有相关现实的库golang.org/x 是 Go 官方团队维护的一个扩展库集合,提供了许多标准库之外的实用功能和工具,虽然不属于Go标准库,但大多数库已经经过广泛测试和使用,具备较高的稳定性和可靠性golang.org/x/text/transform是用于处理文本转换的工具,为文本的编码转换、规范化、过滤等操作提供一个统一的接口和实现框架type Transformer
type Transfor...
在使用Go处理文本(如网页)时,会遇到编码问题,Go的默认编码是UTF-8,遇到其他编码的字符会出错,此时需要对文本进行转换
在Go的官方库中没有编码转换相关库,但是在golang.org/x中有相关现实的库
golang.org/x 是 Go 官方团队维护的一个扩展库集合,提供了许多标准库之外的实用功能和工具,虽然不属于Go标准库,但大多数库已经经过广泛测试和使用,具备较高的稳定性和可靠性
golang.org/x/text/transform
是用于处理文本转换的工具,为文本的编码转换、规范化、过滤等操作提供一个统一的接口和实现框架
type Transformer
type Transformer interface { Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) Reset() // 重置状态,如清空所有缓冲区、错误信息等 } Transform() 将从src读取的字节转换后写入dst,返回写入dst字节数和读取src字节数 atEOF表示是否读取完成 src参数是大小不固定的[]byte,调用方(如transform.Reader)会根据其内部逻辑决定每次读取多少数据到src nDst和nSrc反映的是单次调用中处理的字节数,而不是整个转换过程中累计处理的字节数 预定义错误 ErrShortDst表示dst太短,无法接收所有转换后的字节 ErrShortSrc表示src没有足够的数据来完成转换
包级方法
Append(t Transformer, dst, src []byte) (result []byte, n int, err error) 使用 t 将 src转换的结果追加到 dst result表示src转换后的结果,即追加到dst中的数据 n表示src中成功转换的长度,如err为nil则n等于len(src) Bytes(t Transformer, b []byte) (result []byte, n int, err error) 使用 t 将 b 转换,返回转换后的结果 String(t Transformer, s string) (result string, n int, err error) 使用 t 将 字符串s转换,返回转换后的结果字符串 Chain(t ...Transformer) Transformer 返回一个链式应用所有传入Transformer的Transformer
type NopResetter
用于在实现Transformer接口时嵌入以实现Reset()方法
type NopResetter struct{} func (NopResetter) Reset() 该结构体的Reset方法没有进行任何操作,仅仅是为了实现接口
type Reader
type Reader struct {}
包装一个io.Reader,用来转换读取的字节
NewReader(r io.Reader, t Transformer) *Reader 通过 t 转换读取的 r 中的字节 (r *Reader) Read(p []byte) (int, error) 实现 io.Reader 接口
type Writer
type Writer struct {}
包装一个io.Writer,将要写入的字节转换后写入
NewWriter(w io.Writer, t Transformer) *Writer 通过 t 将写入的数据转换后写入 w (w *Writer) Close() error 实现了io.Closer接口 (w *Writer) Write(data []byte) (n int, err error) 实现了 io.Writer 接口 如果可用字节数不足以完成Transform,则字节将被缓冲以供下一次写入 调用Close()以转换剩余的字节
golang.org/x/text/encoding
定义了用于UTF-8和其他字符编码相互转换的接口
type Decoder
解码器,用于将其他编码转换为UTF-8
type Decoder struct { transform.Transformer // 实现了transform.Transformer接口 }
常用方法
Bytes(b []byte) ([]byte, error) 将给定的编码字节转换为 UTF-8。如果发生任何错误,则返回转换后的字节或 nil,以及错误 Reader(r io.Reader) io.Reader 包装一个 Reader 以解码其字节 解码器在返回的Reader使用期间不得用于任何其他操作 String(s string) (string, error) 将给定的编码字符串转换为 UTF-8。如果发生任何错误,则返回转换后的字符串或空字符串,以及错误
type Encoder
编码器,用于将UTF-8转换为其他编码
type Encoder struct { transform.Transformer // 实现了transform.Transformer接口 }
常用方法
Bytes(b []byte) ([]byte, error) 将UTF-8转换为给定的编码字节。如果发生任何错误,返回转换后的字节或 nil,以及错误 Writer(w io.Writer) io.Writer 包装一个 Writer 以编码为其他编码 编码器在返回的 Writer 被使用期间,不得用于任何其他操作 String(s string) (string, error) 将UTF-8字符串转换为给定的编码。如果发生任何错误,则返回转换后的字符串或空字符串,以及错误
type Encoding
编码方式,是一种可以将字符集编码由UTF-8和其他编码互相转换的方式
type Encoding interface { NewDecoder() *Decoder NewEncoder() *Encoder }
预定义编码方式
var Replacement Encoding = replacement{} 替换编码,该包的默认编码方式 在解码时遇到无效的UTF-8字节时会替换为'\uFFFD' 要提前返回错误,请使用`transform.chain`与`UTF8Validator`预处理数据。 var Nop Encoding = nop{} 在解码时遇到无效的UTF-8字节时不进行替换
golang.org/x/text/encoding/simplifiedchinese
实现了简体中文编码方式
具体的实现我们无需考虑,通过预定于的变量使用即可
var ( GB18030 encoding.Encoding = &gbk18030 GBK encoding.Encoding = &gbk ) GB2312 1980年,中国发布了第一个汉字编码标准GB2312 共收录了6763个常用的汉字和字符并于次年5月实施 GBK 1995年,在GB2312的基础上添加了部分字符形成了GBK 共收录了两万多个汉字和字符并完全兼容GB2312 新增字符:在GB2312标准发布之后简化的汉字、一些人名、繁体字、日语和朝鲜语中的汉 GBK只是 "技术规范指导性文件",并不属于国家标准 GB18030 在GBK的基础上增加了中日韩语中的汉字和少数名族的文字及字符,完全兼容GB2312,基本兼容GBK 共收录七万多个汉字和字符 发布过两个版本,第一版于2000年发布,称为GB18030-2000,第二版于2005年发布,称为GB18030-2005
golang.org/x/net/html/charset
为HTML文档提供了常见的文本编码操作方法
DetermineEncoding(content []byte, contentType string) (e encoding.Encoding, name string, certain bool) 根据content和contentType来推断编码 e表示推断的字符编码方式,如无法确定返回nil name表示推断的字符编码名称,如"utf-8"、"gbk",无法确定返回空字符串 certain表示推断结果是否可信,为false表示推荐可能不准确或无法确定 编码推断步骤: 1、分析contentType,如果存在"charset=utf-8"字样则直接返回 2、分析content中是含有"charset=utf-8"字样的meta标签 3、分析content的前1024个字节 以上步骤只要找到一个就不会继续下面的步骤 Lookup(label string) (e encoding.Encoding, name string) 根据label字符串中的特征字符串来推断编码 如html中的,响应头中Content-Type头的值等 NewReader(r io.Reader, contentType string) (io.Reader, error) 返回一个 io.Reader,将 r 的内容转换为 UTF-8 会调用 DefineEncoding 推断 r 的字符编码 NewReaderLabel(label string, input io.Reader) (io.Reader, error) 返回一个将label字符串转换为 UTF-8 的io.Reader 它调用 Lookup 推断 label 的字符编码 如果 Lookup 返回 nil,则返回错误