文章目录
-
- 一、定义表模型时区问题
-
- 1.1 time.Time 与`int64`
- 1.2 优势
- 二、unique唯一索引字段数据冲突问题
一、定义表模型时区问题
1.1 time.Time 与int64
一般情况下,我们在定义表模型的时候,会使用
// User 直接对应数据库中的表 // 有些人叫做entity,有些人叫做model type User struct { Id int64 `gorm:"primaryKey,autoIncrement"` // 全部用户唯一 Email string `gorm:"unique"` Password string // 创建时间,毫秒数,使用int64解决时区问题 Ctime int64 // 更新时间 Utime int64 }
1.2 优势
在定义数据库表模型时,选择使用
- 时区一致性: 使用
int64 表示时间戳可以避免在前端和后端之间进行时区转换的复杂性。int64 类型的时间戳是相对于某个固定的基准时间(通常是UNIX纪元)的毫秒数,不涉及时区信息。这样,你就可以更轻松地在前端和后端之间传递和处理时间信息,而不必担心时区转换引起的问题。 - 序列化和传输: 使用
int64 类型的时间戳可以更方便地在网络上传输和序列化,因为它是一个数字。对于前后端通信而言,时间戳是一种常见的时间表示方式。 - 易于处理: 在一些情况下,直接使用
int64 类型的时间戳可能更容易处理。例如,你可以轻松进行比较、排序和其他与时间相关的计算,而不涉及时区信息。这在某些业务场景下可能是一种简化处理的方式。 - 避免时区混淆: 时区问题可能引起一系列复杂的 bug,而使用
int64 类型可以避免这些问题,只有返回给用户的时候才需要处理时区问题,数据库存储永远是UTC不会出错。并且前端可以直接使用这个时间戳做转换。
二、unique唯一索引字段数据冲突问题
举个例子,当两个用户同时访问,注册同一个邮箱,当线程1插入会成功,线程2插入不会成功,并且会返回系统错误,这会对用户造成很不好的影响。
所以一般使用唯一索引冲突错误码
// ErrUserDuplicateEmail 表示用户邮箱重复的错误 var ErrUserDuplicateEmail = errors.New("邮箱冲突") // Insert 将用户数据插入数据库 func (dao *UserDAO) Insert(ctx context.Context, u User) error { // 存储当前时间的毫秒数 now := time.Now().UnixNano() u.Ctime = now u.Utime = now // 使用Gorm的Create方法将用户数据插入数据库 err := dao.db.WithContext(ctx).Create(&u).Error // 类型断言,判断是否是MySQL的唯一冲突错误 if mysqlErr, ok := err.(*mysql.MySQLError); ok { const uniqueConflictsErrNo uint16 = 1062 // MySQL错误码1062表示唯一冲突 if mysqlErr.Number == uniqueConflictsErrNo { // 返回自定义的唯一冲突错误 return ErrUserDuplicateEmail } } // 返回其他数据库操作可能出现的错误 return err }