0

0

如何在Golang中处理数据库错误_Golang数据库错误处理与事务管理

P粉602998670

P粉602998670

发布时间:2026-02-04 08:25:03

|

583人浏览过

|

来源于php中文网

原创

应使用 errors.Is(err, sql.ErrNoRows) 判断,因驱动常包装错误导致 == 失效;事务需显式 Rollback/Commit 且仅一次;QueryRow.Scan 错误语义不同于 Exec,前者空结果返回 ErrNoRows,后者非 nil 错误表示执行失败。

如何在golang中处理数据库错误_golang数据库错误处理与事务管理

判断 sql.ErrNoRows 要用 errors.Is,不是 ==

直接用 err == sql.ErrNoRows 在大多数情况下会失效,因为数据库驱动(如 pgxmysql)返回的错误常是包装后的类型。Go 1.13+ 的标准做法是用 errors.Is 判断底层是否为该错误:

err := db.QueryRow("SELECT name FROM users WHERE id = $1", 123).Scan(&name)
if errors.Is(err, sql.ErrNoRows) {
    // 处理未找到
} else if err != nil {
    // 其他错误,如连接失败、语法错等
}
  • sql.ErrNoRows 是哨兵错误(sentinel error),但仅当驱动未包装时才可直接比较
  • 使用 errors.As 可提取具体驱动错误(比如 *pq.Error*mysql.MySQLError)来获取 SQLState 或 errno
  • 别在日志里只打 err.Error() 就完事——它可能不包含原始 SQL,建议同时记录查询语句片段和参数

事务中遇到错误必须显式 tx.Rollback(),不能依赖 defer

常见写法 defer tx.Rollback() 看似安全,但容易掩盖成功提交后的 panic,或在已 Commit() 后重复调用导致 panic("sql: transaction has already been committed or rolled back")。

tx, err := db.Begin()
if err != nil {
    return err
}
defer func() {
    if r := recover(); r != nil {
        tx.Rollback()
        panic(r)
    }
}()

_, err = tx.Exec("INSERT INTO orders (...) VALUES (...)", ...)
if err != nil {
    tx.Rollback() // 显式回滚
    return err
}

return tx.Commit()
  • 所有分支路径(包括 return 前)都必须确保 Rollback()Commit() 被调用且仅调用一次
  • 不要把 tx 传给其他函数再让它决定是否提交——事务生命周期应由入口函数严格控制
  • 若需嵌套逻辑,用函数返回 error 并由外层统一处理回滚,而非让子函数调用 tx.Rollback()

db.QueryRow().Scan()db.Exec() 的错误语义完全不同

QueryRow 类操作的错误只表示“查询执行失败”,不表示“没查到数据”;而 Exec 的错误才真正代表语句未生效。混淆这两者会导致误判业务状态。

成新网络商城购物系统
成新网络商城购物系统

使用模板与程序分离的方式构建,依靠专门设计的数据库操作类实现数据库存取,具有专有错误处理模块,通过 Email 实时报告数据库错误,除具有满足购物需要的全部功能外,成新商城购物系统还对购物系统体系做了丰富的扩展,全新设计的搜索功能,自定义成新商城购物系统代码功能代码已经全面优化,杜绝SQL注入漏洞前台测试用户名:admin密码:admin888后台管理员名:admin密码:admin888

下载
  • db.QueryRow(...).Scan(&v):返回 sql.ErrNoRows 表示查询成功但结果集为空;返回其他错误(如 "pq: invalid input syntax")才是执行失败
  • db.Exec(...):只要返回非 nil 错误,就代表该语句**完全未被数据库执行**(例如约束冲突、权限不足、SQL 语法错)
  • db.Prepare() 错误发生在预编译阶段,与参数无关;而 stmt.Exec(args...) 的错误才和参数及运行时状态相关
  • 批量插入用 db.Exec("INSERT ... VALUES (...), (...), ...") 比循环调用 Exec 更高效,但出错时无法定位哪一行失败

事务隔离级别和上下文超时要按需设置,不是越严越高

默认事务隔离级别因驱动而异(pgx 默认 ReadCommitted,MySQL 默认 RepeatableRead),盲目设成 Serializable 会显著降低并发度,甚至引发死锁。

立即学习go语言免费学习笔记(深入)”;

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

tx, err := db.BeginTx(ctx, &sql.TxOptions{
    Isolation: sql.LevelReadCommitted,
    ReadOnly:  false,
})
  • 读多写少场景(如报表生成)可用 ReadOnly: true 提示驱动优化
  • 超时必须设在 BeginTxcontext 中,而不是靠后续每个 Query 单独设——事务级锁可能卡住整个流程
  • PostgreSQL 的 serializable 事务失败时会返回 "ERROR: could not serialize access due to read/write dependencies",需捕获并重试,Go 标准库不自动重试
事务错误处理最易忽略的一点:不是所有错误都该回滚。比如网络临时抖动导致的 "i/o timeout" 可能需要重试,而主键冲突则应直接返回用户。错误分类得靠 errors.As 提取驱动原生错误类型,再结合业务语义判断。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

184

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

231

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

344

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

210

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

397

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

282

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

196

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

561

2025.06.17

全国统一发票查询平台入口合集
全国统一发票查询平台入口合集

本专题整合了全国统一发票查询入口地址合集,阅读专题下面的文章了解更多详细入口。

19

2026.02.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.1万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 821人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号