vault backup: 2026-05-05 20:22:48

This commit is contained in:
2026-05-05 20:22:48 +08:00
parent 3805434398
commit d094f15d7b
2 changed files with 324 additions and 32 deletions
+3 -32
View File
@@ -30,39 +30,10 @@ type User struct {
## 表名规则
### 默认命名策略
GORM 通过三层优先级推导表名:`db.Table()` → `TableName()` 方法 → struct 名蛇形复数。自定义表名时还涉及 `NamingStrategy` 全局配置、value/pointer receiver 选择、分表策略等细节——详见子文档:
GORM 使用 `Table` 方法来推导表名:
| 代码行为 | 结果 |
|----------|------|
| 默认 | struct 名的蛇形复数形式(`User` → `users`) |
| 实现 `TableName() string` | 返回的字符串 |
| 使用 `db.Table("xxx")` | 本次查询使用的表名(不会修改 Model 的 TableName) |
> [!tip] `TableName()` vs `db.Table()`:何时用哪个?
> - **结构性差异**(多环境、分库分表)→ 用 `TableName()`,因为这是模型级别的约定。
> - **临时覆盖**(一个复杂查询需要 JOIN 不同视图)→ 用 `db.Table()`,它只影响当前链式调用,不污染模型定义。
```go
func (User) TableName() string {
return "sys_user" // 显式指定表名;value receiver 即可,无需接收者变量
}
```
> [!note] 为什么用 value receiver `(User)` 而非 `*User`?
> `TableName()` 只需要返回一个字符串,不需要访问任何字段。GORM 内部会先尝试值接收者方法,找不到再尝试指针接收者——所以用 `(User)` 既能被值对象调用也能被指针对象调用,灵活性更好。
> [!tip] 多环境表名
> 不同环境下表名前缀不同?可以用环境变量 + `TableName()` 实现动态切换:
> ```go
> func (User) TableName() string {
> if os.Getenv("ENV") == "test" {
> return "test_sys_user"
> }
> return "sys_user"
> }
> ```
> [!abstract] 子文档
> - [[02-模型定义/表名规则]] — 默认策略、TableName()、db.Table()、NamingStrategy、分表实战、决策指南
## 字段 Tag 详解