
Go 中的 error 接口不能直接作为 SQL 参数传递,需调用 err.Error() 方法获取字符串表示,再存入数据库;同时应避免使用 error 作为变量名,以防与内置类型冲突。
go 中的 error 接口不能直接作为 sql 参数传递,需调用 `err.error()` 方法获取字符串表示,再存入数据库;同时应避免使用 `error` 作为变量名,以防与内置类型冲突。
在 Go 应用中,当 HTTP 请求失败(如 client.Do(req) 返回非 nil 错误)后,常需将错误信息持久化到数据库以便后续排查。但直接将 error 类型变量传入 db.Exec 会导致运行时 panic:
sql: converting Exec argument #1's type: unsupported type errors.errorString, a struct
这是因为 Go 的 error 是一个接口类型(interface{ Error() string }),而底层具体实现(如 errors.errorString)并非标准 SQL 驱动支持的参数类型(如 string, int, []byte 等)。数据库驱动无法自动序列化任意结构体或接口,必须显式转换。
✅ 正确做法是调用 err.Error() 方法,将其转为 string 后传入 SQL 语句:
resp, err := client.Do(req)
if err != nil {
// ✅ 安全转换:获取错误文本描述
errorMsg := err.Error()
// ✅ 使用有意义的变量名(避免 shadowing 内置类型)
_, dbErr := db.Exec("UPDATE test SET error = $1 WHERE id = $2", errorMsg, id)
if dbErr != nil {
log.Printf("Failed to save error to DB: %v", dbErr)
return "", dbErr
}
return "", err // 或按业务逻辑返回
}⚠️ 注意事项:
- 禁止使用 error 作为变量名:例如 var error error 会遮蔽(shadow)内建 error 类型,导致编译器混淆、IDE 提示异常、代码可读性下降。推荐命名如 err, reqErr, httpErr。
- 空错误处理:err.Error() 在 err == nil 时会 panic,因此务必在非 nil 检查之后调用。
- 敏感信息过滤(生产建议):HTTP 错误可能包含 URL、headers 或堆栈片段,存入数据库前建议清洗或截断(如 strings.TrimSpace(err.Error())[:500]),避免泄露敏感数据或超出字段长度限制。
- 结构化错误(进阶):如需保留错误类型、时间、上下文等,可定义自定义结构体并 JSON 序列化为 string 字段,但需确保数据库列类型为 TEXT 或 JSONB(PostgreSQL)。
总结:Go 的类型安全机制要求显式转换 error → string,err.Error() 是标准且唯一可靠的方式;结合清晰的变量命名与防御性检查,即可稳健实现错误日志的数据库持久化。


















