使用Go驱动向latin1编码MySQL表插入UTF-8文本的编码问题求助
解决UTF-8转MySQL latin1编码插入报错问题
问题根源
核心问题在于MySQL的latin1_swedish_ci对应的字符集并非严格的ISO-8859-1,实际是兼容Windows-1252(cp1252)编码的。比如你示例里的长破折号–,在严格的ISO-8859-1中没有对应字符,会被ReplaceUnsupported替换成无效字符,而MySQL的latin1列只能识别cp1252范围内的单字节字符,这就导致了插入报错。
至于file -I显示binary,是因为编码后的字节包含file工具无法自动识别为常见文本编码的内容,这个不是关键问题,重点还是编码匹配MySQL的要求。
解决方案
替换编码表为Windows-1252
把charmap.ISO8859_1换成charmap.Windows1252,因为MySQL的latin1实际上支持cp1252的扩展字符,像长破折号这类字符能被正确编码为MySQL可识别的单字节,不会被替换成无效内容。确保数据库连接指定latin1字符集
在Go的MySQL驱动DSN中添加charset=latin1参数,避免驱动自动将数据转成UTF-8发送给数据库,示例DSN:user:pass@tcp(host:port)/dbname?charset=latin1&parseTime=true
修改后的示例代码
package main import ( "fmt" "os" "golang.org/x/text/encoding" "golang.org/x/text/encoding/charmap" ) func main() { s := "foo – bar" // 改用Windows-1252编码,匹配MySQL的latin1实际兼容集 encoder := charmap.Windows1252.NewEncoder() encoder = encoding.ReplaceUnsupported(encoder) encoded, err := encoder.String(s) if err != nil { panic(err) } fmt.Println(s) fmt.Println(encoded) fmt.Printf("%q\n", encoded) // 此时encoded中的长破折号会被编码为0x96,属于MySQL latin1的有效字节 /* file test */ f, err := os.Create("file.txt") if err != nil { panic(err) } defer f.Close() w := encoder.Writer(f) w.Write([]byte(s)) }
额外验证
可以打印编码后的字节值确认是否符合要求:
fmt.Printf("%x\n", []byte(encoded))
对于foo – bar,应该输出666f6f209620626172,其中96就是cp1252中长破折号的字节,这个在MySQL的latin1列中是合法的。
内容的提问来源于stack exchange,提问作者argot
相关产品推荐
相关产品推荐

