gorm连接数据库需正确配置dsn并调用gorm.open获取*gorm.db,必须执行automigrate建表;主键和时间字段需正确标记tag;first查不到记录时返回gorm.errrecordnotfound,须用errors.is判断;save全量更新非零值,updates可精确控制字段;默认软删除,真删用unscoped;多表操作需显式事务。

如何用 GORM 连接数据库并初始化 gorm.DB
不配好连接,后面所有 Create、First 都会 panic 或返回空值。GORM 不会自动帮你建库,得先确保 MySQL/PostgreSQL 服务在运行,且账号有对应库的权限。
常见错误是把 user:password@/dbname 写成 user:password@tcp(127.0.0.1:3306)/dbname 却忘了加 ?charset=utf8mb4&parseTime=True&loc=Local,结果时间字段解析失败或中文乱码。
- MySQL 推荐 DSN 格式:
user:pass@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local - 用
gorm.Open(mysql.Open(dsn), &gorm.Config{})获取*gorm.DB,不是直接 new - 务必调用
db.AutoMigrate(&User{})—— 它只建表、不改结构,字段少或类型变时不会自动同步
Create 插入数据时主键和默认值怎么处理
GORM 默认用 struct tag gorm:"primaryKey" 找主键,如果没标,它会尝试用 ID 字段;若字段名不是 ID(比如叫 uid),又没显式声明主键,Create 会静默失败或报 missing primary key 错误。
时间字段如 CreatedAt、UpdatedAt 会被自动填充,但前提是字段名匹配或打了 gorm:"autoCreateTime" 等 tag。自己定义的默认值(如 status=0)得靠 gorm:"default:0",否则 DB 层 null,GORM 不会帮你补。
- 插入前检查 struct 是否有
gorm.Model嵌入,或至少一个gorm:"primaryKey"字段 - 想跳过零值字段插入(比如不传
Name就让它用 DB 默认值),用db.Select("Name", "Age").Create(&u) -
Create返回的 error 是唯一约束冲突、NOT NULL 违反等真实 DB 错误,不是“插入成功与否”的布尔值
为什么 First 查不到记录却没报错
First、Take、Last 这类方法查不到时返回 gorm.ErrRecordNotFound,但很多人只判 err != nil,没细分错误类型,结果把记录不存在当成其他错误(比如连不上库)处理了。
更隐蔽的是:如果用 db.First(&u, "name = ?", "foo"),而 name 字段没建索引,慢查询可能被误认为超时;或者 struct 字段名和数据库列名不一致(比如 DB 是 user_name,struct 是 UserName 又没加 gorm:"column:user_name"),导致查到空对象但无提示。
- 永远用
errors.Is(err, gorm.ErrRecordNotFound)判断“没找到”,而不是err == nil反推 - 查单条优先用
First(按主键升序),要最新一条用Last,不确定是否存在用Take - 条件查询建议用 map 或 struct 传参,比字符串拼接更安全:
db.Where(User{Name: "foo"}).First(&u)
Save 和 Updates 改数据的区别在哪
Save 是全量更新:它会把 struct 所有非零字段(int=0、string=""、time.Time{} 都算零值)都写进 SQL,哪怕你只改了一个字段;而 Updates 默认只更新非零字段,但如果你传 map 或 struct 指定字段,就会精确更新那些字段。
典型坑是:用户 struct 里有个 Age int 字段,原值是 25,前端传了个 0 上来,用 Save 会导致 DB 被改成 0;但用 Updates(map[string]interface{}{"age": 0}) 就能正确写入。
- 想更新部分字段且允许设零值,必须用
Updates+ map 或指定字段名:db.Model(&u).Select("Age").Updates(User{Age: 0}) -
Delete默认是软删除(加DeletedAt),真删要用Unscoped().Delete - 批量更新慎用
Model(&User{}).Where(...).Updates(...),WHERE 条件漏写会全表更新
最常被忽略的是事务控制 —— GORM 的 Create/Update 默认不带事务,多表关联操作或需要原子性时,必须显式用 db.Transaction(func(tx *gorm.DB) error { ... }) 包一层,否则中间出错没法回滚。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











