# 約定
## 使用 `ID` 作為主鍵
默認情況下,GORM 會使用 `ID` 作為表的主鍵。
```go
type User struct {
ID string // 默認情況下,名為 `ID` 的字段會作為表的主鍵
Name string
}
```
你可以通過標簽 `primaryKey` 將其它字段設為主鍵
```go
// 將 `AnimalID` 設為主鍵
type Animal struct {
ID int64
UUID string `gorm:"primaryKey"`
Name string
Age int64
}
```
此外,您還可以看看 [復合主鍵](http://v2.gorm.io/zh_CN/docs/composite_primary_key.html)
## 復數表名
GORM 使用結構體名的 `蛇形命名` 作為表名。對于結構體 `User`,根據約定,其表名為 `users`
### TableName
您可以實現 `Tabler` 接口來更改默認表名,例如:
```go
type Tabler interface {
TableName() string
}
// TableName 會將 User 的表名重寫為 `profiles`
func (User) TableName() string {
return "profiles"
}
```
**注意:** `TableName` 不支持動態變化,它會被緩存下來以便后續使用。想要使用動態表名,你可以使用下面的代碼:
```go
func UserTable(user User) func (db *gorm.DB) *gorm.DB {
return func (db *gorm.DB) *gorm.DB {
if user.Admin {
return db.Table("admin_users")
}
return db.Table("users")
}
}
DB.Scopes(UserTable(user)).Create(&user)
```
### 臨時指定表明
您可以使用 `Table` 方法臨時指定表名,例如:
```go
// 根據 User 的字段創建 `deleted_users` 表
db.Table("deleted_users").AutoMigrate(&User{})
// 從另一張表查詢數據
var deletedUsers []User
db.Table("deleted_users").Find(&deletedUsers)
// SELECT * FROM deleted_users;
db.Table("deleted_users").Where("name = ?", "jinzhu").Delete(&User{})
// DELETE FROM deleted_users WHERE name = 'jinzhu';
```
查看 [from 子查詢](http://v2.gorm.io/zh_CN/docs/advanced_query.html#from_subquery) 了解如何在 FROM 子句中使用子查詢
### 命名策略
GORM 允許用戶通過覆蓋默認的`命名策略`更改默認的命名約定,命名策略被用于構建: `TableName`、`ColumnName`、`JoinTableName`、`RelationshipFKName`、`CheckerName`、`IndexName`。查看 [GORM 配置](http://v2.gorm.io/zh_CN/docs/gorm_config.html) 獲取詳情
## 列名
根據約定,數據表的列名使用的是 struct 字段名的 `蛇形命名`
```go
type User struct {
ID uint // 列名是 `id`
Name string // 列名是 `name`
Birthday time.Time // 列名是 `birthday`
CreatedAt time.Time // 列名是 `created_at`
}
```
您可以使用標簽 `column` 或 [`命名策略`](http://v2.gorm.io/zh_CN/docs/conventions.html#naming_strategy) 來覆蓋列名
```go
type Animal struct {
AnimalID int64 `gorm:"column:beast_id"` // 將列名設為 `beast_id`
Birthday time.Time `gorm:"column:day_of_the_beast"` // 將列名設為 `day_of_the_beast`
Age int64 `gorm:"column:age_of_the_beast"` // 將列名設為 `age_of_the_beast`
}
```
## 時間戳追蹤
### CreatedAt
對于有 `CreatedAt` 字段的模型,創建記錄時,如果該字段值為零值,則將該字段的值設為當前時間
```go
db.Create(&user) // 將 `CreatedAt` 設為當前時間
// 想要修改該字段的值,你可以使用 `Update`
db.Model(&user).Update("CreatedAt", time.Now())
```
### UpdatedAt
對于有 `UpdatedAt` 字段的模型,更新記錄時,將該字段的值設為當前時間。創建記錄時,如果該字段值為零值,則將該字段的值設為當前時間
```go
db.Save(&user) // 將 `UpdatedAt` 設為當前時間
db.Model(&user).Update("name", "jinzhu") // 也會將 `UpdatedAt` 設為當前時間
```
**注意** GORM 支持擁有多種類型的時間追蹤字段。可以根據 UNIX 秒、納秒、其它類型追蹤時間,查看 [模型](http://v2.gorm.io/zh_CN/docs/models.html#time_tracking) 獲取詳情