
本文详解如何使用 go 语言安全、高效地从 mysql 查询多条记录,映射为结构体切片,并封装进指定键(如 "data")的 json 对象中,涵盖字段导出规则、sql 字段匹配、错误处理及 json 序列化全流程。
本文详解如何使用 go 语言安全、高效地从 mysql 查询多条记录,映射为结构体切片,并封装进指定键(如 "data")的 json 对象中,涵盖字段导出规则、sql 字段匹配、错误处理及 json 序列化全流程。
在 Go 中将 MySQL 查询结果转换为结构化 JSON,需严格遵循 Go 的导出规则与 database/sql 包的使用规范。首先,结构体字段必须以大写字母开头(即导出字段),否则 json.Marshal 无法访问,导致对应字段在 JSON 中为空或被忽略。因此,应将 Customer 结构体定义为:
type Customer struct {
ID int `json:"id"`
Name string `json:"name"`
Surname string `json:"surname"`
}注意:原始问题中 id 为小写且类型为 IntegerType(非标准 Go 类型),需替换为 int 并首字母大写;同时修正拼写错误(如 Surnmae → Surname)。
接下来,构建一个顶层容器结构体(或匿名结构),用于将 []Customer 封装至 "data" 键下:
result := struct {
Data []Customer `json:"data"`
}{}执行查询时,*强烈建议显式指定字段名而非使用 `SELECT **,以避免字段顺序错位、新增列导致Scan` 失败等问题:
rows, err := db.Query("SELECT id, name, surname FROM Customers")
if err != nil {
log.Fatal("Query failed:", err)
}
defer rows.Close()在 rows.Next() 循环中逐行扫描并构造 Customer 实例:
for rows.Next() {
var c Customer
if err := rows.Scan(&c.ID, &c.Name, &c.Surname); err != nil {
log.Printf("Scan error: %v", err)
continue // 或根据业务选择中断
}
result.Data = append(result.Data, c)
}
if err := rows.Err(); err != nil {
log.Fatal("Rows iteration error:", err)
}⚠️ 关键注意事项:
- 必须调用 rows.Err() 检查循环结束后的潜在错误(如网络中断、类型不匹配);
- rows.Scan 参数地址必须与 SQL 字段顺序、类型严格一致;
- 若数据库字段可能为 NULL,应使用 sql.NullString 等可空类型替代原生 string/int。
最后,序列化为 JSON 字节流:
jsonData, err := json.Marshal(result)
if err != nil {
log.Fatal("JSON marshal failed:", err)
}
// jsonData 是 []byte,可直接写入 HTTP 响应或保存文件
fmt.Println(string(jsonData))输出示例:
{"data":[{"id":1,"name":"Alice","surname":"Smith"},{"id":2,"name":"Bob","surname":"Johnson"}]}总结:整个流程核心在于 —— 导出字段 + 显式查询 + 严格 Scan + 容器封装 + 完整错误检查。避免使用 SELECT * 和未导出字段,是保障稳定性和可维护性的关键实践。


















