
Go 应用通过 sqlx 向 MariaDB 插入中文、波斯文等非 ASCII 字符时出现 ???,根本原因在于数据库层级的字符集未统一为 UTF-8,仅修改表或列的 collation 不足以生效,需同步设置数据库级默认字符集并转换表结构。
go 应用通过 sqlx 向 mariadb 插入中文、波斯文等非 ascii 字符时出现 `???`,根本原因在于数据库层级的字符集未统一为 utf-8,仅修改表或列的 collation 不足以生效,需同步设置数据库级默认字符集并转换表结构。
在 Go 中使用 sqlx 或原生 database/sql 操作 MariaDB 时,若表中非 ASCII 字符(如简体中文、波斯语)保存后变成 ???,即使表已设为 utf8_general_ci 或 utf8_unicode_ci,问题仍存在——这通常不是 Go 代码或连接层的问题,而是 MySQL/MariaDB 的字符集配置不完整所致。
关键误区在于:仅执行 ALTER TABLE quote CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci 是不够的。MySQL 的字符集生效遵循“数据库 → 表 → 列”三级继承机制。若数据库(schema)本身默认字符集仍是 latin1,新建列或隐式转换仍可能退化为 latin1,导致客户端发送的 UTF-8 字节被错误解释。
✅ 正确修复步骤如下:
-
确保数据库级字符集为 UTF-8(推荐
utf8mb4,而非过时的utf8):ALTER DATABASE mydb CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
-
转换表及其所有字段为
utf8mb4(注意:utf8在 MySQL 中仅支持 BMP 字符,无法存储 emoji 或部分生僻汉字;utf8mb4才是真正的 UTF-8):ALTER TABLE quote CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-
验证配置是否生效:
-- 查看数据库默认字符集 SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'mydb'; -- 查看表字符集 SHOW CREATE TABLE quote;
-
Go 连接字符串中显式指定字符集(强烈建议):
// 在 DSN 中添加 charset=utf8mb4 dsn := "user:password@tcp(127.0.0.1:3306)/mydb?charset=utf8mb4&parseTime=true&loc=Local" db, err := sqlx.Connect("mysql", dsn)
⚠️ 注意事项:
-
utf8mb4是 MySQL 对 UTF-8 的完整实现(支持 4 字节 Unicode),而utf8实际是阉割版(仅 3 字节),务必使用前者; - 修改后需重启应用连接池,旧连接可能缓存旧字符集设置;
- 确保前端 HTML 表单
<form></form>声明accept-charset="UTF-8",且 HTTP 响应头包含Content-Type: text/html; charset=UTF-8; - Go 字符串本身是 UTF-8 编码,无需额外转码——只要数据库和连接层正确配置,
content和author参数可直接安全插入。
完成上述配置后,QuoteCreate("你好,世界", "张三") 将正确存入并可正常查询返回,终端打印与数据库存储完全一致。











