# 編寫插件
## Callbacks
GORM 自身也是基于 `Callbacks` 的,包括 `Create`、`Query`、`Update`、`Delete`、`Row`、`Raw`。此外,您也完全可以根據自己的意愿自定義 GORM
回調會注冊到全局 `*gorm.DB`,而不是會話級別。如果您想要 `*gorm.DB` 具有不同的回調,您需要初始化另一個 `*gorm.DB`
### 注冊回調
注冊回調至 callbacks
```go
func cropImage(db *gorm.DB) {
if db.Statement.Schema != nil {
// 偽代碼:裁剪圖片字段并將其上傳至 CDN
for _, field := range db.Statement.Schema.Fields {
switch db.Statement.ReflectValue.Kind() {
case reflect.Slice, reflect.Array:
for i := 0; i < db.Statement.ReflectValue.Len(); i++ {
// 從字段獲取 value
if fieldValue, isZero := field.ValueOf(db.Statement.ReflectValue.Index(i)); !isZero {
if crop, ok := fieldValue.(CropInterface); ok {
crop.Crop()
}
}
}
case reflect.Struct:
// 從字段獲取 value
if fieldValue, isZero := field.ValueOf(db.Statement.ReflectValue); isZero {
if crop, ok := fieldValue.(CropInterface); ok {
crop.Crop()
}
}
// 設置字段的 value
err := field.Set(db.Statement.ReflectValue, "newValue")
}
}
// 當前 model 的所有字段
db.Statement.Schema.Fields
// 當前 model 的所有主鍵字段
db.Statement.Schema.PrimaryFields
// 優先的主鍵字段:DB 列名為 `id` 或定義的第一個主鍵
db.Statement.Schema.PrioritizedPrimaryField
// 當前 model 的所有關系
db.Statement.Schema.Relationships
field := db.Statement.Schema.LookUpField("Name")
// 處理...
}
}
db.Callback().Create().Register("crop_image", cropImage)
// 為 Crete 流程注冊一個回調
```
### 刪除回調
從 callbacks 中刪除回調
```go
db.Callback().Create().Remove("gorm:create")
// 從 Create 的 callbacks 中刪除 `gorm:create`
```
### 替換回調
用一個新的回調替換已有的同名回調
```go
db.Callback().Create().Replace("gorm:create", newCreateFunction)
// 用新函數 `newCreateFunction` 替換 Create 流程目前的 `gorm:create`
```
### 注冊帶順序的回調
注冊帶順序的回調
```go
db.Callback().Create().Before("gorm:create").Register("update_created_at", updateCreated)
db.Callback().Create().After("gorm:create").Register("update_created_at", updateCreated)
db.Callback().Query().After("gorm:query").Register("my_plugin:after_query", afterQuery)
db.Callback().Delete().After("gorm:delete").Register("my_plugin:after_delete", afterDelete)
db.Callback().Update().Before("gorm:update").Register("my_plugin:before_update", beforeUpdate)
db.Callback().Create().Before("gorm:create").After("gorm:before_create").Register("my_plugin:before_create", beforeCreate)
```
### 預定義回調
GORM 已經定義了 [一些回調](https://github.com/go-gorm/gorm/blob/master/callbacks/callbacks.go) 來支持當前的 GORM 功能,在啟動您的插件之前可以先看看這些回調
## 插件
GORM 提供了 `Use` 方法來注冊插件,插件需要實現 `Plugin` 接口
```go
type Plugin interface {
Name() string
Initialize(*gorm.DB) error
}
```
當插件首次注冊到 GORM 時將調用 `Initialize` 方法,且 GORM 會保存已注冊的插件,你可以這樣訪問訪問:
```go
db.Config.Plugins[pluginName]
```
查看 [Prometheus](http://v2.gorm.io/zh_CN/docs/prometheus.html) 的例子