You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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的要求。

解决方案

  1. 替换编码表为Windows-1252
    把charmap.ISO8859_1换成charmap.Windows1252,因为MySQL的latin1实际上支持cp1252的扩展字符,像长破折号这类字符能被正确编码为MySQL可识别的单字节,不会被替换成无效内容。

  2. 确保数据库连接指定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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:05:15