秒杀
This commit is contained in:
142
kills/kill.go
Normal file
142
kills/kill.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package kills
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"math/rand"
|
||||
"time"
|
||||
"toutoukan/init/databaseInit"
|
||||
)
|
||||
|
||||
const (
|
||||
colorRed = "\033[31m" // 红色
|
||||
colorGreen = "\033[32m" // 绿色
|
||||
colorYellow = "\033[33m" // 黄色
|
||||
colorBlue = "\033[34m" // 蓝色
|
||||
colorReset = "\033[0m" // 重置颜色
|
||||
)
|
||||
|
||||
type Goods struct {
|
||||
GID uint `gorm:"column:gid"`
|
||||
Stock int `gorm:"column:stock"`
|
||||
StartTime time.Time `gorm:"column:start_time"`
|
||||
EndTime time.Time `gorm:"column:end_time"`
|
||||
}
|
||||
|
||||
// Order 订单模型,对应 orders_list 表
|
||||
type Order struct {
|
||||
OrderId string `gorm:"column:order_id"` // 关联商品ID
|
||||
TradeTime time.Time `gorm:"column:trade_time"`
|
||||
}
|
||||
|
||||
// 为模型指定数据库表名
|
||||
func (Goods) TableName() string {
|
||||
return "goods_list"
|
||||
}
|
||||
|
||||
func (Order) TableName() string {
|
||||
return "oders_list"
|
||||
}
|
||||
|
||||
// 生成25位随机订单编号(string类型)
|
||||
func GenerateOrderID() string {
|
||||
// 1. 取当前时间戳(精确到毫秒,8位数字)
|
||||
timestamp := time.Now().Format("20060102150405") // 年月日时分秒(14位)
|
||||
|
||||
// 2. 生成随机字符串(11位,补足25位)
|
||||
randomBytes := make([]byte, 8) // 8字节随机数经base64编码后约11字符
|
||||
_, err := rand.Read(randomBytes)
|
||||
if err != nil {
|
||||
// 出错时降级为伪随机数
|
||||
return fmt.Sprintf("ORD%s%011d", timestamp, time.Now().UnixNano()%100000000000)
|
||||
}
|
||||
|
||||
// 3. 拼接前缀+时间戳+随机字符串(确保25位)
|
||||
randomStr := base64.URLEncoding.EncodeToString(randomBytes)[:11] // 截取前11位
|
||||
return fmt.Sprintf("ORD%s%s", timestamp, randomStr)
|
||||
}
|
||||
|
||||
func Userkill(c *gin.Context) {
|
||||
// 直接使用全局初始化好的 UserDB 连接池
|
||||
db := databaseInit.UserDB
|
||||
if db == nil {
|
||||
log.Printf("%sUserDB 未初始化,请先调用 InitUserDB()%s\n", colorRed, colorReset)
|
||||
c.JSON(500, gin.H{"error": "系统数据库未初始化"})
|
||||
return
|
||||
}
|
||||
fmt.Printf("%s用户请求处理完成%s\n", colorBlue, colorReset)
|
||||
|
||||
// 定义要查询的商品ID
|
||||
var targetGID uint = 1
|
||||
var goods Goods
|
||||
|
||||
tx := db.Begin()
|
||||
if tx.Error != nil {
|
||||
log.Printf("%s开启事务失败: %v%s\n", colorRed, tx.Error, colorReset)
|
||||
c.JSON(500, gin.H{"body": "事务开启失败"})
|
||||
return
|
||||
}
|
||||
result := tx.Set("gorm:query_option", "FOR UPDATE").Where("gid = ?", targetGID).First(&goods)
|
||||
if result.Error != nil {
|
||||
tx.Rollback() // 失败回滚事务
|
||||
log.Printf("%s查询商品失败: %v%s\n", colorRed, result.Error, colorReset)
|
||||
c.JSON(404, gin.H{"error": "商品不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 检查库存是否充足
|
||||
if goods.Stock <= 0 {
|
||||
tx.Rollback()
|
||||
log.Printf("%s商品库存不足%s\n", colorYellow, colorReset)
|
||||
c.JSON(400, gin.H{"error": "商品库存不足"})
|
||||
return
|
||||
}
|
||||
|
||||
// 3. 生成订单
|
||||
order := Order{
|
||||
OrderId: GenerateOrderID(),
|
||||
TradeTime: time.Now(),
|
||||
}
|
||||
if err := tx.Create(&order).Error; err != nil {
|
||||
tx.Rollback()
|
||||
log.Printf("%s创建订单失败: %v%s\n", colorRed, err, colorReset)
|
||||
c.JSON(500, gin.H{"error": "创建订单失败"})
|
||||
return
|
||||
}
|
||||
|
||||
updateResult := tx.Model(&Goods{}).
|
||||
Where("gid = ? AND stock > 0", targetGID).
|
||||
Update("stock", gorm.Expr("stock - 1"))
|
||||
if updateResult.Error != nil {
|
||||
tx.Rollback()
|
||||
log.Printf("%s扣减库存失败: %v%s\n", colorRed, updateResult.Error, colorReset)
|
||||
c.JSON(500, gin.H{"error": "库存更新失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 5. 检查库存是否实际被扣减(防止并发下库存已被其他事务耗尽)
|
||||
if updateResult.RowsAffected == 0 {
|
||||
tx.Rollback()
|
||||
log.Printf("%s库存扣减失败:并发冲突,库存已不足%s\n", colorRed, colorReset)
|
||||
c.JSON(400, gin.H{"error": "商品库存不足"})
|
||||
return
|
||||
}
|
||||
|
||||
// 5. 提交事务
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
log.Printf("%s提交事务失败: %v%s\n", colorRed, err, colorReset)
|
||||
c.JSON(500, gin.H{"error": "系统错误"})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("%s订单创建成功,订单ID: %s,剩余库存: %d%s\n", colorGreen, order.OrderId, goods.Stock-1, colorReset)
|
||||
c.JSON(200, gin.H{
|
||||
"message": "下单成功",
|
||||
"order_id": order.OrderId,
|
||||
"stock": goods.Stock - 1,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user