
go 中的 error 接口不能直接作为 sql 参数传递,需调用其 error() 方法获取字符串表示,再写入数据库;同时应避免使用 error 作为变量名,以防类型冲突和可读性下降。
go 中的 error 接口不能直接作为 sql 参数传递,需调用其 error() 方法获取字符串表示,再写入数据库;同时应避免使用 error 作为变量名,以防类型冲突和可读性下降。
在 Go 应用中,当 HTTP 请求失败(如 client.Do(req) 返回非 nil 错误)并需将错误信息持久化到数据库时,常见误区是直接将 error 类型变量传入 db.Exec() 的参数列表。例如:
_, err = db.Exec("UPDATE test SET error = $1 WHERE id = $2", error, id)这段代码会触发运行时错误:sql: converting Exec argument #1's type: unsupported type errors.errorString, a struct。原因在于:Go 的 error 是一个接口类型(interface{ Error() string }),而标准 database/sql 包不支持直接序列化任意接口或结构体——它仅支持基础类型(如 string, int, bool)、指针、切片及部分扫描兼容类型。
✅ 正确做法是显式调用 err.Error() 获取错误的字符串描述:
if err != nil {
errorMsg := err.Error() // ✅ 转换为 string
_, execErr := db.Exec("UPDATE test SET error = $1 WHERE id = $2", errorMsg, id)
if execErr != nil {
log.Printf("Failed to save error to DB: %v", execErr)
return "", execErr
}
return "", err // 或按业务逻辑返回
}⚠️ 重要注意事项:
- 禁止使用 error 作为变量名:如 var error error 会遮蔽内置类型名,导致编译歧义和 IDE 提示异常。应改用语义清晰的名称,如 reqErr、apiErr 或 httpErr;
- 空错误需防御性处理:err 为 nil 时调用 err.Error() 会 panic,因此务必先判空;
- 敏感信息脱敏:生产环境不应直接存储原始错误(尤其含路径、凭证、堆栈等),建议记录日志后存摘要,或使用 fmt.Sprintf("HTTP request failed: %v", err) 增强可读性;
- 考虑结构化存储:若需长期分析错误,可额外增加字段如 error_type(err.(net.Error) 类型判断)、error_code(HTTP 状态码)等。
总结:error.Error() 是将错误转为数据库友好字符串的标准方式,配合规范命名与空值检查,即可安全、可靠地实现错误状态的持久化追踪。


















