vault backup: 2026-05-05 20:22:48
This commit is contained in:
+3
-32
@@ -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 详解
|
||||
|
||||
|
||||
Reference in New Issue
Block a user