开发者

Go语言结合GORM实现数据库事务处理的示例代码

开发者 https://www.devze.com 2025-08-21 10:45 出处:网络 作者: 程序员爱钓鱼
目录一、事务的基本概念二、GORM 事务处理方式三、实战案例:用户转账1. 定义模型2. 使用事务完成转账3. 测试转账四、运行效果五、事务处理注意事项六、总结在实际业务中,很多操作需要保证 要么全部成功,要么全部失
目录
  • 一、事务的基本概念
  • 二、GORM 事务处理方式
  • 三、实战案例:用户转账
    • 1. 定义模型
    • 2. 使用事务完成转账
    • 3. 测试转账
  • 四、运行效果
    • 五、事务处理注意事项
      • 六、总结

        在实际业务中,很多操作需要保证 要么全部成功,要么全部失败,否则可能造成数据不一致。比如:

        • 用户转账(A 账户扣款,B 账户加款)
        • 下单支付(生成订单、扣减库存、记录支付)

        这种场景就需要用到 事务(Transaction)

        本文将带你使用 Go 语言 + GORM 实现数据库事务处理。

        一、事务的基本概念

        事务(Transaction)是数据库中一组不可分割的操作单元,具有四大特性(ACID):

        • 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败。
        • 一致性(Consistency):事务执行前后,数据必须保持一致。
        • 隔离性(Isolation):多个事务之间相互独立,互不干扰。
        • 持久性(Durability):事务一旦提交,结果会永久保存。

        二、GORM 事务处理方式

        GORM 提供了三种事务使用方式:

        • 手动开启、提交、回滚
        • db.Transaction() 包裹函数(推荐)
        • 嵌套事务(SavePoint / RollbackTo)

        三、实战案例:用户转账

        我们以一个“用户转账”的例子来演示事务操作。

        1. 定义模型

        package main
        
        import (
        	"fm编程客栈t"
        	"gorm.io/driver/mysql"
        	"gorm.io/gorm"
        	"log"
        )
        
        type User struct {
        	ID      uint   `gorm:"primaryKey"`
        	Name    string `gorm:"size:100"`
        	Balance int    // 账户余额
        }
        
        var db *gorm.DB
        
        func initDB() {
        	dsn := "root:123456@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
        	var err error
        	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
        	if err != nil {
        		log.Fatal("数据库连接失败:", err)
        	}
        	_ = db.AutoMigrate(&User{})
        }
        

        2. 使用事务完成转账

        // Transfer 转账函数:fromID -> toID,金额 amount
        func Transfer(fromID, toID uint, amount int) error {
        	return db.Transaction(func(tx *gorm.DB) error {
        		var from, to User
        
        		// 查询转出账户
        		if err := tx.First(&from, fromID).Error; err != nil {
        			return err
        		}
        		if from.Balance < amount {
        			returnhttp://www.devze.com fmt.Errorf("余额不足")
        		}
        
        		// 扣减余额
        		if err := tx.Model(&from).Update("balance", from.Balance-amount).Error; err != nil {
        			return err
        		}
        
        		// 查询转入账户
        		if err := tx.First(&to, toID).Error; err != nil {
        			return err
        		}
        
        		// 增加余额
        		if err := tx.Model(&to).Update("balance", to.Balance+amount).Error; err != nil {
        			return err
        		}
        
        		// 所有操作成功 -> 提交事务
        		return nil
        	})
        }
        

        3. 测试转账

        func main() {
        	initDB()
        
        	// 初始化两位用户
        	db.Create(&User{Name: "Alice", Balance: 100})
        	db.Create(&User{Name: "Bob", Balance: 50})
        
        	// 转账:Alice -> Bob 30元
        	err := Transfer(1, 2, 30)
        	if err != nil {
        		log.Println("转账失败:", err)
        	} else {
        		log.Println("转账成功")
        	}
        
        	var users []User
        	db.Find(&users)
        	log.Println("当前用户余额:", users)
        }
        

        四、运行效果

        初始状态:

        Alice: 100

        Bob:   50

        转账成功后:

        Alice: 70

        Bob:   80

        如果 Alice 余额不足,事务会回滚:

        转账失败: 余额不足

        Alice: 100

        Bob:编程客栈   50

        五、事务处理注意事项

        事务函数返回 error

        • 返回 nil → 提交事务
        • 返回 error → 回滚事务

        不要在事务中使用全局 db

        必须用传入的 tx 对象,确保操作在同一事务内。

        事务适合小而快的操作

        长时间事务会占用锁,可能导致性能下降。

        六、总结

        通过本案例,我们学习了:

        • 事务的编程基本概念(ACID)
        • GORM 的事务 API(推荐 db.Transactionphp()
        • 用事务实现 用户转账 功能

        事务在业务中非常常见,掌握它能让你的数据库操作更加安全可靠。

        到此这篇关于Go语言结合GORM实现数据库事务处理的示例代码的文章就介绍到这了,更多相关Go语言数据库事务处理内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

        0

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        关注公众号