宣告模型

GORM 透過將 Go 結構對應到資料庫表格,簡化了資料庫互動。了解如何在 GORM 中宣告模型,對於充分發揮其功能至關重要。

宣告模型

模型使用一般結構定義。這些結構可以包含具有基本 Go 類型、指標或這些類型的別名,甚至自訂類型的欄位,只要它們實作了 ScannerValuer 介面(來自 database/sql 套件)

考慮以下 User 模型範例

type User struct {
ID uint // Standard field for the primary key
Name string // A regular string field
Email *string // A pointer to a string, allowing for null values
Age uint8 // An unsigned 8-bit integer
Birthday *time.Time // A pointer to time.Time, can be null
MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
ActivatedAt sql.NullTime // Uses sql.NullTime for nullable time fields
CreatedAt time.Time // Automatically managed by GORM for creation time
UpdatedAt time.Time // Automatically managed by GORM for update time
}

在此模型中

  • 直接使用基本資料類型,例如 uintstringuint8
  • 指向類型(例如 *string*time.Time)的指標表示可為 Null 的欄位。
  • database/sql 套件中的 sql.NullStringsql.NullTime 用於具有更多控制項的可為 Null 欄位。
  • CreatedAtUpdatedAt 是特殊欄位,GORM 會在建立或更新記錄時自動填入目前時間。

除了 GORM 中模型宣告的基本功能外,重要的是要強調透過序列化標籤支援序列化。此功能增強了從資料庫儲存和擷取資料的彈性,特別是對於需要自訂序列化邏輯的欄位,請參閱 序列化 以取得詳細說明

慣例

  1. 主鍵:GORM 使用名為 ID 的欄位作為每個模型的預設主鍵。

  2. 資料表名稱:預設情況下,GORM 會將結構名稱轉換為 snake_case 並將其複數化以作為資料表名稱。例如,User 結構在資料庫中會變成 users

  3. 欄位名稱:GORM 會自動將結構欄位名稱轉換為 snake_case 以作為資料庫中的欄位名稱。

  4. 時間戳記欄位:GORM 使用名為 CreatedAtUpdatedAt 的欄位來自動追蹤記錄的建立和更新時間。

遵循這些慣例可以大幅減少您需要撰寫的設定或程式碼量。然而,GORM 也具備彈性,讓您可以在預設慣例不符合您的需求時自訂這些設定。您可以在 GORM 的慣例文件進一步了解如何自訂這些慣例。

gorm.Model

GORM 提供了一個預先定義的結構,名為 gorm.Model,其中包含常用的欄位

// gorm.Model definition
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
  • 嵌入在您的結構中:您可以直接將 gorm.Model 嵌入在您的結構中,以自動包含這些欄位。這對於在不同的模型之間維持一致性以及利用 GORM 內建的慣例很有用,請參閱嵌入式結構

  • 包含的欄位:

    • ID:每個記錄的唯一識別碼(主鍵)。
    • CreatedAt:在建立記錄時自動設定為目前的時刻。
    • UpdatedAt:在更新記錄時自動更新為目前的時刻。
    • DeletedAt:用於軟刪除(將記錄標記為已刪除,但不會實際從資料庫中移除)。

進階

欄位層級權限

使用 GORM 執行 CRUD 時,已匯出的欄位具有所有權限,而 GORM 允許您使用標籤變更欄位層級權限,因此您可以將欄位設為唯讀、唯寫、唯建立、唯更新或忽略

注意使用 GORM Migrator 建立資料表時,會忽略欄位

type User struct {
Name string `gorm:"<-:create"` // allow read and create
Name string `gorm:"<-:update"` // allow read and update
Name string `gorm:"<-"` // allow read and write (create and update)
Name string `gorm:"<-:false"` // allow read, disable write permission
Name string `gorm:"->"` // readonly (disable write permission unless it configured)
Name string `gorm:"->;<-:create"` // allow read and create
Name string `gorm:"->:false;<-:create"` // createonly (disabled read from db)
Name string `gorm:"-"` // ignore this field when write and read with struct
Name string `gorm:"-:all"` // ignore this field when write, read and migrate with struct
Name string `gorm:"-:migration"` // ignore this field when migrate with struct
}

建立/更新時間/Unix (毫秒/奈秒) 秒數追蹤

GORM 使用 CreatedAtUpdatedAt 根據慣例追蹤建立/更新時間,如果已定義這些欄位,GORM 會在建立/更新時設定目前時間

若要使用不同名稱的欄位,可以使用標籤 autoCreateTimeautoUpdateTime 設定這些欄位

如果你偏好儲存 UNIX(毫秒/奈秒)秒數,而非時間,你可以簡單地將欄位的資料類型從 time.Time 變更為 int

type User struct {
CreatedAt time.Time // Set to current time if it is zero on creating
UpdatedAt int // Set to current unix seconds on updating or if it is zero on creating
Updated int64 `gorm:"autoUpdateTime:nano"` // Use unix nano seconds as updating time
Updated int64 `gorm:"autoUpdateTime:milli"`// Use unix milli seconds as updating time
Created int64 `gorm:"autoCreateTime"` // Use unix seconds as creating time
}

Embedded Struct

對於匿名欄位,GORM 會將其欄位納入其父結構中,例如

type User struct {
gorm.Model
Name string
}
// equals
type User struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Name string
}

對於一般結構欄位,你可以使用標籤 embedded 將其嵌入,例如

type Author struct {
Name string
Email string
}

type Blog struct {
ID int
Author Author `gorm:"embedded"`
Upvotes int32
}
// equals
type Blog struct {
ID int64
Name string
Email string
Upvotes int32
}

你可以使用標籤 embeddedPrefix 為嵌入欄位的資料庫名稱新增前綴,例如

type Blog struct {
ID int
Author Author `gorm:"embedded;embeddedPrefix:author_"`
Upvotes int32
}
// equals
type Blog struct {
ID int64
AuthorName string
AuthorEmail string
Upvotes int32
}

欄位標籤

宣告模型時,標籤是可選的,GORM 支援下列標籤
標籤不分大小寫,不過建議使用 camelCase

標籤名稱 說明
column 資料庫欄位名稱
type 欄位資料類型,建議使用相容的一般類型,例如:bool、int、uint、float、string、time、bytes,這些類型適用於所有資料庫,且可以與其他標籤一起使用,例如 not nullsizeautoIncrement… 也可以使用指定的資料庫資料類型,例如 varbinary(8),使用指定的資料庫資料類型時,必須是完整的資料庫資料類型,例如:MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT
serializer 指定序列化器,說明如何將資料序列化和反序列化到資料庫中,例如:serializer:json/gob/unixtime
size 指定欄位資料大小/長度,例如:size:256
primaryKey 指定欄位為主要鍵
unique 指定欄位為唯一
default 指定欄位的預設值
precision 指定欄位的精度
scale 指定欄位的縮放
not null 指定欄位為 NOT NULL
autoIncrement 指定欄位為自動遞增
autoIncrementIncrement 自動遞增步長,控制連續欄位值之間的間隔
embedded 嵌入欄位
embeddedPrefix 嵌入欄位的欄位名稱前綴
autoCreateTime 建立時追蹤目前時間,對於 int 欄位,它會追蹤 Unix 秒數,使用值 nano/milli 來追蹤 Unix 奈秒/毫秒,例如:autoCreateTime:nano
autoUpdateTime 建立/更新時追蹤目前時間,對於 int 欄位,它會追蹤 Unix 秒數,使用值 nano/milli 來追蹤 Unix 奈秒/毫秒,例如:autoUpdateTime:milli
index 使用選項建立索引,對多個欄位使用相同名稱會建立複合索引,有關詳細資訊,請參閱 索引
uniqueIndex index 相同,但會建立唯一索引
check 建立檢查約束,例如:check:age > 13,請參閱 約束
<- 設定欄位的寫入權限,<-:create 僅建立欄位,<-:update 僅更新欄位,<-:false 沒有寫入權限,<- 建立和更新權限
-> 設定欄位的讀取權限,->:false 沒有讀取權限
- 忽略這個欄位,- 沒有讀取/寫入權限,-:migration 沒有遷移權限,-:all 沒有讀取/寫入/遷移權限
comment 遷移時為欄位新增註解

關聯標籤

GORM 允許透過關聯的標籤來設定外來鍵、約束、多對多表格,有關詳細資訊,請查看 關聯區段

白金贊助商

金牌贊助商

白金贊助商

金牌贊助商