feat(auth): 添加完整的用户认证API项目

- 实现用户注册、登录、JWT令牌认证功能
- 集成Gin、GORM、Viper、Zap等框架
- 添加密码加密、数据库操作、中间件等完整功能
- 配置多环境支持、日志轮转、CORS处理
- 创建完整的项目结构和配置文件体系
This commit is contained in:
liumangmang
2025-12-30 18:00:42 +08:00
parent 7f4527d501
commit b010f82221
139 changed files with 2772 additions and 103 deletions

View File

@@ -0,0 +1,71 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Orders []Order
//}
//
//type Order struct {
// ID uint `gorm:"primaryKey"`
// UserID uint
// Product string `gorm:"size:100"`
// Amount int
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{}, &Order{})
//user := User{Name: "Alice"}
//db.Create(&user)
//查询用户根据名称
var user User
db.Where("name = ?", "Alice").First(&user)
//order1 := Order{Product: "Laptop"}
//order2 := Order{Product: "Mouse"}
//order3 := Order{Product: "Keyboard"}
// 1. Append - 添加关联
//db.Model(&user).Association("Orders").Append(&order1, &order2)
//fmt.Println("Orders appended")
// 2. Count - 统计关联数量
//count := db.Model(&user).Association("Orders").Count()
//fmt.Printf("Order count: %d\n", count)
// 4. Replace - 替换所有关联
//db.Model(&user).Association("Orders").Replace(&order3)
//查询订单 Keyboard
var order3 Order
db.Where("product = ?", "Keyboard").First(&order3)
// 5. Delete - 删除关联(不删除记录本身)
//db.Model(&user).Association("Orders").Delete(&order3)
//fmt.Println("Association deleted")
//fmt.Println("Orders replaced with Keyboard")
// 6. Clear - 清空所有关联
//db.Model(&user).Association("Orders").Append(&order3)
db.Model(&user).Association("Orders").Clear()
fmt.Println("All associations cleared")
// 3. Find - 查找关联
var orders []Order
db.Model(&user).Association("Orders").Find(&orders)
fmt.Println("Orders found:")
for _, o := range orders {
fmt.Printf(" - %s\n", o.Product)
}
}

View File

@@ -0,0 +1,51 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
// Age int
// CreatedAt time.Time
// }
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{})
// 1. 单条插入
user := User{
Name: "Alice",
Email: "alice@example.com",
Age: 30,
}
result := db.Create(&user)
if result.Error != nil {
panic(result.Error)
}
fmt.Printf("New user ID: %d\n", user.ID)
fmt.Printf("Rows affected: %d\n", result.RowsAffected)
// 2. 批量插入
users := []User{
{Name: "Bob", Email: "bob@example.com", Age: 25},
{Name: "Charlie", Email: "charlie@example.com", Age: 35},
{Name: "David", Email: "david@example.com", Age: 28},
}
db.Create(users)
fmt.Println("Batch insert completed!")
// 3. 指定字段插入
user2 := User{Name: "Eve", Email: "eve@example.com", Age: 22}
db.Select("name", "email").Create(&user2) // 仅插入 name 和 email
fmt.Println("All users created successfully!")
}

View File

@@ -0,0 +1,56 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
// Age int
// DeletedAt gorm.DeletedAt `gorm:"index"` // 软删除字段
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{})
//// 插入测试数据
//users := []User{
// {Name: "Alice", Email: "alice@example.com", Age: 30},
// {Name: "Bob", Email: "bob@example.com", Age: 25},
// {Name: "Charlie", Email: "charlie@example.com", Age: 35},
//}
//db.Create(users)
// 1. 软删除(标记 deleted_at
db.Delete(&User{}, 11) // 删除 ID=1 的用户
fmt.Println("Soft deleted user ID=1")
// 2. 查询时默认不包括已删除的
var activeUsers []User
db.Find(&activeUsers)
fmt.Printf("Active users: %d\n", len(activeUsers))
// 3. 查询所有记录(包括已删除的)
var allUsers []User
db.Unscoped().Find(&allUsers)
fmt.Printf("All users (including deleted): %d\n", len(allUsers))
// 4. 永久删除(硬删除)
db.Unscoped().Delete(&User{}, 12)
fmt.Println("Permanently deleted user ID=2")
// 5. 批量删除
db.Where("age < ?", 30).Delete(&User{})
fmt.Println("Batch delete completed")
// 最终统计
var finalCount int64
db.Model(&User{}).Count(&finalCount)
fmt.Printf("Final active users: %d\n", finalCount)
}

View File

@@ -0,0 +1,72 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
// Age int
// CreatedAt time.Time
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
// 先插入测试数据
db.AutoMigrate(&User{})
db.Create(&User{Name: "Alice", Email: "alice@example.com", Age: 30})
db.Create(&User{Name: "Bob", Email: "bob@example.com", Age: 25})
db.Create(&User{Name: "Charlie", Email: "charlie@example.com", Age: 35})
// 1. 根据 ID 查询
var user User
db.First(&user, 1) // 查询 ID=1 的用户
fmt.Printf("User ID=1: %s (%s)\n", user.Name, user.Email)
// 2. 按条件查询单条
var user2 User
db.Where("email = ?", "bob@example.com").First(&user2)
fmt.Printf("User by email: %s (age=%d)\n", user2.Name, user2.Age)
// 3. 查询所有
var users []User
db.Find(&users)
fmt.Printf("Total users: %d\n", len(users))
// 4. 按条件查询多条
var adults []User
db.Where("age >= ?", 30).Find(&adults)
fmt.Printf("Users age >= 30: %d\n", len(adults))
// 5. 使用 IN 查询
var selectedUsers []User
db.Where("id IN ?", []int{1, 2}).Find(&selectedUsers)
fmt.Printf("Selected users: %d\n", len(selectedUsers))
// 6. 排序查询
var sortedUsers []User
db.Order("age DESC").Find(&sortedUsers)
fmt.Println("Users sorted by age (DESC):")
for _, u := range sortedUsers {
fmt.Printf(" - %s (age=%d)\n", u.Name, u.Age)
}
// 7. 分页查询
var pageUsers []User
db.Offset(0).Limit(2).Find(&pageUsers)
fmt.Printf("Page 1 (limit 2): %d users\n", len(pageUsers))
// 8. 组合查询
var combinedUsers []User
db.Where("age > ?", 25).
Order("age DESC").
Limit(2).
Find(&combinedUsers)
fmt.Printf("Combined query: %d users\n", len(combinedUsers))
}

View File

@@ -0,0 +1,56 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
// Age int
// UpdatedAt time.Time
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{})
// 插入测试数据
user := User{Name: "Alice", Email: "alice@example.com", Age: 30}
db.Create(&user)
// 1. 更新单个字段
db.Model(&User{}).Where("id = ?", user.ID).Update("name", "Alice Updated")
fmt.Println("Updated single field")
// 2. 更新多个字段(使用 map
db.Model(&User{}).Where("id = ?", user.ID).Updates(map[string]interface{}{
"name": "Alice Smith",
"age": 31,
})
fmt.Println("Updated multiple fields (map)")
// 3. 更新多个字段(使用 struct仅更新非零值
db.Model(&User{}).Where("id = ?", user.ID).Updates(User{
Name: "Alice Johnson",
Age: 32,
})
fmt.Println("Updated multiple fields (struct)")
// 4. 强制更新零值字段
db.Model(&User{}).Where("id = ?", user.ID).Update("age", 0)
fmt.Println("Updated age to zero")
// 5. 批量更新
db.Model(&User{}).Where("age > ?", 25).Update("age", gorm.Expr("age + ?", 1))
fmt.Println("Batch update completed")
// 查询最终结果
var finalUser User
db.First(&finalUser, user.ID)
fmt.Printf("Final user: %s (age=%d)\n", finalUser.Name, finalUser.Age)
}

View File

@@ -0,0 +1,29 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func main() {
// 连接 SQLite文件数据库
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
fmt.Println("Database connected successfully!")
// 获取底层的 *sql.DB
sqlDB, err := db.DB()
if err != nil {
panic(err)
}
// 设置连接池
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
fmt.Println("Connection pool configured")
}

View File

@@ -0,0 +1,11 @@
module go-gorm-demo
go 1.22.2
require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/mattn/go-sqlite3 v1.14.17 // indirect
gorm.io/driver/sqlite v1.5.4 // indirect
gorm.io/gorm v1.25.5 // indirect
)

View File

@@ -0,0 +1,10 @@
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0=
gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=

View File

@@ -0,0 +1,28 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// // User 模型
//
// type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100;not null"`
// Email string `gorm:"size:100;unique;not null"`
// Age int `gorm:"default:0"`
// Active bool `gorm:"default:true"`
// CreatedAt time.Time
// UpdatedAt time.Time
// }
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
// 自动迁移(创建表)
db.AutoMigrate(&User{})
fmt.Println("Table created successfully!")
}

View File

@@ -0,0 +1,63 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100"`
Profile Profile
Orders []Order
}
type Profile struct {
ID uint `gorm:"primaryKey"`
UserID uint
Bio string `gorm:"size:200"`
}
type Order struct {
ID uint `gorm:"primaryKey"`
UserID uint
Product string `gorm:"size:100"`
}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{}, &Profile{}, &Order{})
// 创建测试数据
//user := User{
// Name: "Alice",
// Profile: Profile{Bio: "Software Engineer"},
// Orders: []Order{
// {Product: "Laptop"},
// {Product: "Mouse"},
// },
//}
//db.Create(&user)
// 1. 预加载单个关联
//var user1 User
//db.Preload("Profile").First(&user1, 1)
//fmt.Printf("User: %s, Bio: %s\n", user1.Name, user1.Profile.Bio)
//// 2. 预加载多个关联
//var user2 User
//db.Preload("Profile").Preload("Orders").First(&user2, 1)
//fmt.Printf("User: %s, Orders: %d\n", user2.Name, len(user2.Orders))
// 3. 预加载所有关联
//var user3 User
//db.Preload("Profile").Preload("Orders").First(&user3, 1)
//fmt.Printf("Fully loaded user: %s\n", user3.Name)
//// 4. 条件预加载
var user4 User
db.Preload("Orders", "product = ?", "Laptop").First(&user4, 1)
fmt.Printf("Filtered orders: %d\n", len(user4.Orders))
}

View File

@@ -0,0 +1,76 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
// Age int
// Active bool `gorm:"default:true"`
// CreatedAt time.Time
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{})
// 插入测试数据
users := []User{
{Name: "Alice", Email: "alice@example.com", Age: 30, Active: true},
{Name: "Bob", Email: "bob@example.com", Age: 25, Active: false},
{Name: "Charlie", Email: "charlie@example.com", Age: 35, Active: true},
{Name: "David", Email: "david@example.com", Age: 28, Active: true},
}
db.Create(users)
// 1. 多条件查询
var result1 []User
db.Where("age > ? AND active = ?", 25, true).Find(&result1)
fmt.Printf("Age > 25 AND active: %d users\n", len(result1))
// 2. OR 查询
var result2 []User
db.Where("age < ? OR active = ?", 30, false).Find(&result2)
fmt.Printf("Age < 30 OR inactive: %d users\n", len(result2))
// 3. 模糊查询
var result3 []User
db.Where("name LIKE ?", "%li%").Find(&result3)
fmt.Printf("Name contains 'li': %d users\n", len(result3))
// 4. 仅查询指定字段
var result4 []User
db.Select("name", "email").Find(&result4)
fmt.Printf("Selected fields: %d users\n", len(result4))
for _, u := range result4 {
fmt.Printf(" - %s (%s)\n", u.Name, u.Email)
}
// 5. 统计查询
var count int64
db.Model(&User{}).Where("active = ?", true).Count(&count)
fmt.Printf("Active users count: %d\n", count)
// 6. 聚合查询
var avgAge float64
db.Model(&User{}).Select("AVG(age)").Row().Scan(&avgAge)
fmt.Printf("Average age: %.2f\n", avgAge)
// 7. 分组查询
type Result struct {
Active bool
Count int64
}
var groupResult []Result
db.Model(&User{}).Select("active, count(*) as count").Group("active").Scan(&groupResult)
fmt.Println("Group by active:")
for _, r := range groupResult {
fmt.Printf(" Active=%v: %d users\n", r.Active, r.Count)
}
}

View File

@@ -0,0 +1,47 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
// Age int
// Active bool `gorm:"default:true"`
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{})
// 插入测试数据
db.Create(&User{Name: "Alice", Email: "alice@example.com", Age: 30})
db.Create(&User{Name: "Bob", Email: "bob@example.com", Age: 25})
// 1. 原生查询
var users []User
db.Raw("SELECT * FROM users WHERE age > ?", 20).Scan(&users)
fmt.Printf("Raw query result: %d users\n", len(users))
// 2. 原生更新
db.Exec("UPDATE users SET age = age + 1 WHERE name = ?", "Alice")
fmt.Println("Raw update executed")
// 3. 原生统计
var count int64
db.Raw("SELECT COUNT(*) FROM users").Scan(&count)
fmt.Printf("Total users: %d\n", count)
// 4. 查询单行
var result struct {
Name string
Age int
}
db.Raw("SELECT name, age FROM users WHERE id = ?", 1).Scan(&result)
fmt.Printf("User: %s (age=%d)\n", result.Name, result.Age)
}

View File

@@ -0,0 +1,61 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// 用户拥有多个订单
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Orders []Order // 一对多关联
//}
//
//type Order struct {
// ID uint `gorm:"primaryKey"`
// UserID uint // 外键
// Product string `gorm:"size:100"`
// Amount int
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{}, &Order{})
// 1. 创建用户和订单
user := User{
Name: "Alice",
Orders: []Order{
{Product: "Laptop", Amount: 1},
{Product: "Mouse", Amount: 2},
{Product: "Keyboard", Amount: 1},
},
}
db.Create(&user)
fmt.Println("User and orders created")
// 2. 预加载查询
var result User
db.Preload("Orders").First(&result, user.ID)
fmt.Printf("User: %s, Orders: %d\n", result.Name, len(result.Orders))
for _, order := range result.Orders {
fmt.Printf(" - %s (x%d)\n", order.Product, order.Amount)
}
// 3. 添加新订单
newOrder := Order{UserID: user.ID, Product: "Monitor", Amount: 1}
db.Create(&newOrder)
fmt.Println("New order added")
// 4. 查询用户的所有订单
var orders []Order
db.Where("user_id = ?", user.ID).Find(&orders)
fmt.Printf("Total orders: %d\n", len(orders))
// 5. 删除某个订单
db.Delete(&Order{}, orders[0].ID)
fmt.Println("First order deleted")
}

View File

@@ -0,0 +1,51 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// 用户拥有一个账户
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Account Account // 一对一关联
// Email string `gorm:"size:100;unique"`
//}
//
//type Account struct {
// ID uint `gorm:"primaryKey"`
// UserID uint // 外键
// Balance int
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{}, &Account{})
// 1. 创建用户和账户
user := User{
Name: "Alice",
Account: Account{Balance: 1000},
}
db.Create(&user)
fmt.Println("User and account created")
// 2. 预加载查询
var result User
db.Preload("Account").First(&result, user.ID)
fmt.Printf("User: %s, Balance: %d\n", result.Name, result.Account.Balance)
// 3. 更新关联数据
db.Model(&result.Account).Update("balance", 2000)
fmt.Println("Account balance updated")
// 4. 删除关联(不会自动删除 Account
db.Delete(&result)
var accountCount int64
db.Model(&Account{}).Count(&accountCount)
fmt.Printf("Account still exists: %d\n", accountCount)
}

View File

@@ -0,0 +1,96 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// 学生和课程:多对多关系
type Student struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100"`
Courses []Course `gorm:"many2many:student_courses;"` // 多对多
}
type Course struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100"`
Students []Student `gorm:"many2many:student_courses;"` // 多对多
}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
//db.AutoMigrate(&Student{}, &Course{})
// 1. 创建课程
//math := Course{Name: "Math"}
//physics := Course{Name: "Physics"}
//chemistry := Course{Name: "Chemistry"}
//db.Create(&math)
//db.Create(&physics)
//db.Create(&chemistry)
// 2. 创建学生并关联课程
//alice := Student{
// Name: "Alice",
// Courses: []Course{math, physics},
//}
//bob := Student{
// Name: "Bob",
// Courses: []Course{physics, chemistry},
//}
//db.Create(&alice)
//db.Create(&bob)
//fmt.Println("Students and courses created")
//查询数据库的alice的学生
var alice Student
db.Where("name = ?", "Alice").First(&alice)
//查询数据库的Bob学生
var bob Student
db.Where("name = ?", "Bob").First(&bob)
//查询课程
var math Course
db.Where("name = ?", "Math").First(&math)
//// 5. 添加关联
//db.Model(&alice).Association("Courses").Append(&chemistry)
//fmt.Println("Alice enrolled in Chemistry")
//// 7. 替换所有关联
//db.Model(&alice).Association("Courses").Replace(&math)
//fmt.Println("Alice now only takes Math")
// 8. 清空关联
db.Model(&bob).Association("Courses").Clear()
fmt.Println("Bob dropped all courses")
// 3. 查询学生的课程
var student1 Student
db.Preload("Courses").First(&student1, 1)
fmt.Printf("%s's courses:\n", student1.Name)
for _, course := range student1.Courses {
fmt.Printf(" - %s\n", course.Name)
}
// 4. 查询课程的学生
var course1 Course
db.Preload("Students").First(&course1, 1)
fmt.Printf("%s course students:\n", course1.Name)
for _, student := range course1.Students {
fmt.Printf(" - %s\n", student.Name)
}
//查询bob的课程
var student2 Student
db.Preload("Courses").First(&student2, 2)
fmt.Printf("%s's courses:\n", student2.Name)
for _, course := range student2.Courses {
fmt.Printf(" - %s\n", course.Name)
}
}

Binary file not shown.

View File

@@ -0,0 +1,70 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
// Age int
//}
//
//type Account struct {
// ID uint `gorm:"primaryKey"`
// UserID uint
// Balance int
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{}, &Account{})
// 1. 手动事务
tx := db.Begin()
// 创建用户
user := User{Name: "Alice", Email: "alice@example.com"}
if err := tx.Create(&user).Error; err != nil {
tx.Rollback()
panic(err)
}
// 创建账户
account := Account{UserID: user.ID, Balance: 1000}
if err := tx.Create(&account).Error; err != nil {
tx.Rollback()
panic(err)
}
// 提交事务
tx.Commit()
fmt.Println("Transaction committed successfully!")
// 2. 自动事务(推荐)
err := db.Transaction(func(tx *gorm.DB) error {
// 在事务中执行操作
user2 := User{Name: "Bob", Email: "bob@example.com"}
if err := tx.Create(&user2).Error; err != nil {
return err // 自动回滚
}
account2 := Account{UserID: user2.ID, Balance: 2000}
if err := tx.Create(&account2).Error; err != nil {
return err // 自动回滚
}
// 返回 nil 自动提交
return nil
})
if err != nil {
fmt.Println("Transaction failed:", err)
} else {
fmt.Println("Auto transaction committed successfully!")
}
}

View File

@@ -0,0 +1,47 @@
package main
import (
"errors"
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
// }
//type Account struct {
// ID uint `gorm:"primaryKey"`
// UserID uint
// Balance int
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{}, &Account{})
// 故意触发错误,测试回滚
err := db.Transaction(func(tx *gorm.DB) error {
user := User{Name: "Charlie", Email: "charlie@example.com"}
if err := tx.Create(&user).Error; err != nil {
return err
}
fmt.Println("User created, ID:", user.ID)
// 故意返回错误,触发回滚
return errors.New("something went wrong")
})
if err != nil {
fmt.Println("Transaction rolled back:", err)
}
// 检查用户是否存在
var count int64
db.Model(&User{}).Where("name = ?", "Charlie").Count(&count)
fmt.Printf("User 'Charlie' count: %d (should be 0)\n", count)
}

View File

@@ -0,0 +1,37 @@
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
//type User struct {
// ID uint `gorm:"primaryKey"`
// Name string `gorm:"size:100"`
// Email string `gorm:"size:100;unique"`
//}
func main() {
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{})
db.Transaction(func(tx *gorm.DB) error {
tx.Create(&User{Name: "Alice", Email: "alice@example.com"})
// 创建 SavePoint
tx.SavePoint("sp1")
tx.Create(&User{Name: "Bob", Email: "bob@example.com"})
// 回滚到 SavePoint
tx.RollbackTo("sp1")
return nil
})
// 检查结果
var count int64
db.Model(&User{}).Count(&count)
fmt.Printf("Total users: %d (should be 1, only Alice)\n", count)
}