Предисловие:gormЭто библиотека ORM с отличной производительностью на языке Golang, которая относительно дружелюбна к разработчикам. Конечно есть ещеxormБиблиотека тоже довольно известная, если вам интересно, вы тоже можете взглянуть на эту библиотеку, далее мы в основном познакомимся с ней.
gorm
Некоторое базовое использование библиотеки.
Введение в GORM и быстрый старт
Обзор функций
- Полнофункциональный ORM (бесконечная близость)
- Ассоциация (имеет один, имеет много, принадлежит, многие ко многим, полиморфизм)
- Hook-функция Hook (до или после создания/сохранения/обновления/удаления/поиска)
- Предварительная загрузка
- дела
- составной первичный ключ
- Генератор SQL
- Автоматическая миграция базы данных
- пользовательский журнал
- Возможность расширения для написания плагинов на основе обратных вызовов GORM
- Все функции покрыты тестами
- дружественный к разработчику
Установить
Все мы знаем, что некоторые пакеты драйверов необходимо использовать в golang для работы с указанной базой данных, например, для MySQL необходимо использоватьgithub.com/go-sql-driver/mysql
библиотека, в то время как Sqlite должен использоватьgithub.com/mattn/go-sqlite3
Библиотека для поддержки, но к счастью, каждый пакет драйверов просто запакован в фреймворк gorm, что позволяет более удобно управлять библиотекой драйверов при написании программ.
Поддерживаемые базы данных и пути импорта:
- mysql: github.com/jinzhu/gorm/dialects/mysql
- postgres: github.com/jinzhu/gorm/dialects/postgres
- sqlite: github.com/jinzhu/gorm/dialects/sqlite
- sqlserver: github.com/jinzhu/gorm/dialects/mssql
注意:
Платформа gorm просто инкапсулирует пакет драйверов базы данных, и вам все равно нужно загрузить исходный пакет драйверов во время установки.
# 由于在项目中使用mysql比较多,这里使用mysql进行数据存储
$ go get -u github.com/jinzhu/gorm
$ go get -u github.com/go-sql-driver/mysql
Быстрый старт
# 使用docker快速创建一个本地可连接的mysql实例
$ docker run -itd -e MYSQL_ROOT_PASSWORD='bgbiao.top' --name go-orm-mysql -p 13306:3306 mysql:5.6
# 登陆mysql并创建一个测试库
$ docker exec -it go-orm-mysql mysql -uroot -pbgbiao.top
....
mysql> create database test_api;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test_api |
+--------------------+
4 rows in set (0.00 sec)
# 运行一个简单示例
$ cat gorm-mysql-example.go
package main
import (
"fmt"
"time"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
// 定义一个数据模型(user表)
// 列名是字段名的蛇形小写(PassWd->pass_word)
type User struct {
Id uint `gorm:"AUTO_INCREMENT"`
Name string `gorm:"size:50"`
Age int `gorm:"size:3"`
Birthday *time.Time
Email string `gorm:"type:varchar(50);unique_index"`
PassWord string `gorm:"type:varchar(25)"`
}
var db *gorm.DB
func main() {
db,err := gorm.Open("mysql","root:bgbiao.top@(127.0.0.1:13306)/test_api?charset=utf8&parseTime=True&loc=Local")
if err != nil {
fmt.Errorf("创建数据库连接失败:%v",err)
}
defer db.Close()
// 自动迁移数据结构(table schema)
// 注意:在gorm中,默认的表名都是结构体名称的复数形式,比如User结构体默认创建的表为users
// db.SingularTable(true) 可以取消表名的复数形式,使得表名和结构体名称一致
db.AutoMigrate(&User{})
// 添加唯一索引
db.Model(&User{}).AddUniqueIndex("name_email", "id", "name","email")
// 插入记录
db.Create(&User{Name:"bgbiao",Age:18,Email:"bgbiao@bgbiao.top"})
db.Create(&User{Name:"xxb",Age:18,Email:"xxb@bgbiao.top"})
var user User
var users []User
// 查看插入后的全部元素
fmt.Printf("插入后元素:\n")
db.Find(&users)
fmt.Println(users)
// 查询一条记录
db.First(&user,"name = ?","bgbiao")
fmt.Println("查看查询记录:",user)
// 更新记录(基于查出来的数据进行更新)
db.Model(&user).Update("name","biaoge")
fmt.Println("更新后的记录:",user)
// 删除记录
db.Delete(&user)
// 查看全部记录
fmt.Println("查看全部记录:")
db.Find(&users)
fmt.Println(users)
}
# 运行gorm实例
$ go run gorm-mysql-example.go
插入后元素:
[{1 bgbiao 18 <nil> bgbiao@bgbiao.top } {2 xxb 18 <nil> xxb@bgbiao.top }]
查看查询记录: {1 bgbiao 18 <nil> bgbiao@bgbiao.top }
更新后的记录: {1 biaoge 18 <nil> bgbiao@bgbiao.top }
查看全部记录:
[{2 xxb 18 <nil> xxb@bgbiao.top }]
Часто используемые функции GORM
Автоматическая миграция
注意:
Использование режима автоматической миграции будет поддерживать актуальность таблицы, но не будет обновлять индексы и типы существующих столбцов или удалять неиспользуемые столбцы.
// 同时迁移多个模型
db.AutoMigrate(&User{}, &Product{}, &Order{})
// 创建表时增加相关参数
// 比如修改表的字符类型CHARSET=utf8
db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})
контрольный список
// 检查模型是否存在
db.HasTable(&User{})
// 检查表是否存在
db.HasTable("users")
Добавить, удалить, изменить структуру таблицы
注意:
В производственной среде реального предприятия обычно операции изменения уровня базы данных должны быть преобразованы в SQL и переданы братьям администраторам баз данных для помощи с онлайновыми изменениями таблиц базы данных. на стадии среды разработки.
// 使用模型创建
db.CreateTable(&User{})
// 增加参数创建
db.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&User{})
// 删除表
db.DropTable(&User{})
db.DropTable("users")
// 模型和表名的混搭
db.DropTableIfExists(&User{}, "products")
// 修改列(修改字段类型)
db.Model(&User{}).ModifyColumn("description", "text")
// 删除列
db.Model(&User{}).DropColumn("description")
// 指定表名创建表
db.Table("deleted_users").CreateTable(&User{})
// 指定表名查询
var deleted_users []User
db.Table("deleted_users").Find(&deleted_users)
Индексы и ограничения
// 添加外键
// 1st param : 外键字段
// 2nd param : 外键表(字段)
// 3rd param : ONDELETE
// 4th param : ONUPDATE
db.Model(&User{}).AddForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT")
// 单个索引
db.Model(&User{}).AddIndex("idx_user_name", "name")
// 多字段索引
db.Model(&User{}).AddIndex("idx_user_name_age", "name", "age")
// 添加唯一索引(通常使用多个字段来唯一标识一条记录)
db.Model(&User{}).AddUniqueIndex("idx_user_name", "name")
db.Model(&User{}).AddUniqueIndex("idx_user_name_age", "name", "id","email")
// 删除索引
db.Model(&User{}).RemoveIndex("idx_user_name")
Рассмотрение модели GORM
горм.Модель структуры
по фактуgorm
В примере официального документа в атрибуты модели будет добавлен дефолтgorm.ModelПервоначальная структура атрибута выглядит следующим образом:
// 官方示例模型
type User struct {
gorm.Model
Name string
.....
}
// gorm.Model结构体
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
Очевидно, что когда мы добавляем определяемую пользователем модельgorm.Model
, он автоматически добавит в нашу таблицуid,created_at,updated_at,deleted_at
Четыре поля.
Следует также отметить, что когда наша модель имеетCreatedAt
,UpdatedAt
,DeletedAt
свойство и типtime.Time
или*time.Time
Когда есть операция данных, соответствующее время будет автоматически обновлено.
Поэтому при определении модели вы можете решить, вводить ли ее в соответствии с реальными потребностями.gorm.Model
структура
Также обратите внимание: нулевые значения для всех полей, например.0, '', false 或者其它零值
не будут сохранены в базе данных, а будут использовать значения по умолчанию, поэтому можно использовать некоторые необязательные поляDEFAULT
Поле тега для объявления значения столбца по умолчанию.
Теги, поддерживаемые моделью горма
注意:
gorm поддерживает некоторые общие теги для настройки расширенной информации полей модели.
структурный тег | описывать |
---|---|
column | Перечислено (по умолчанию используется строчная буква змеи в поле) |
type | тип данных |
size | длина столбца |
PRIMARY_KEY | объявить первичный ключ |
UNIQUE | объявить уникальным |
DEFAULT | Укажите значение по умолчанию |
PRECISION | Заявленная точность столбца |
NOT NULL | Укажите столбец как не NULL |
AUTO_INCREMENT | Заявлен автоинкремент |
INDEX | Создайте индекс с именем или без него или создайте составной индекс, если несколько индексов имеют одно и то же имя. |
UNIQUE_INDEX | Создать уникальный индекс |
EMBEDDED | Установите структуру для встраивания |
EMBEDDED_PREFIX | Установить префикс для встроенной структуры |
- | игнорировать это поле |
注意:
gorm также поддерживает некоторые связанные структурные теги, такие как внешние ключи, связанные внешние ключи и другие операции.Обычно в сложных корпоративных средах рекомендуется проектировать связанные таблицы как изолированные таблицы при проектировании библиотечных таблиц.Конкретная логика ассоциации определяется бизнес-уровень для достижения (может увеличить стоимость разработки, но когда развитие бизнеса более сложное, это, несомненно, удобно для последующего расширения и оптимизации)
Подробный интерфейс CRUD
Создайте
вставить запись
// 相当于insert into users(name,age,brithday) values("BGBiao",18,time.Now())
user := User{Name: "BGBiao", Age: 18, Birthday: time.Now()}
// 主键为空返回`true`
db.NewRecord(user)
db.Create(&user)
// 创建`user`后返回`false`
db.NewRecord(user)
Установка значений полей в хуках
注意
: Обычно, когда мы разрабатываем модель, у нас есть исходные поля, и мы надеемся получить записи после инициализации модели. В настоящее время мы можем использовать хуки для вставки исходных записей.
если хотитеBeforeCreate
Чтобы изменить значение поля в хуке, вы можете использоватьscope.SetColumn
:
func (user *User) BeforeCreate(scope *gorm.Scope) error {
scope.SetColumn("ID", uuid.New())
return nil
}
Создать параметры расширения
// 为Instert语句添加扩展SQL选项
// insert into produce(name,code) values("name","code") on conflict;
db.Set("gorm:insert_option", "ON CONFLICT").Create(&product)
Запрос
Базовый запрос
// 根据主键查询第一条记录
// SELECT * FROM users ORDER BY id LIMIT 1;
db.First(&user)
// 随机获取一条记录
// SELECT * FROM users LIMIT 1;
db.Take(&user)
// 根据主键查询最后一条记录
// SELECT * FROM users ORDER BY id DESC LIMIT 1;
db.Last(&user)
// 查询所有的记录
// SELECT * FROM users;
db.Find(&users)
// 查询指定的某条记录(仅当主键为整型时可用)
// SELECT * FROM users WHERE id = 10;
db.First(&user, 10)
Запрос режима структуры
// 结构体方式
// select * from users where name = 'bgbiao.top'
db.Where(&User{Name: "bgbiao.top", Age: 20}).First(&user)
// Map方式
// select * from users where name = 'bgbiao.top' and age = 20;
db.Where(map[string]interface{}{"name": "bgbiao.top", "age": 20}).Find(&users)
// 主键的切片
// select * from users where id in (20,21,22);
db.Where([]int64{20, 21, 22}).Find(&users)
Где условие запроса
注意:
Используется метод Where(), который в основном представляет собой базовый синтаксис sql.
// 使用条件获取一条记录 First()方法
db.Where("name = ?", "bgbiao.top").First(&user)
// 获取全部记录 Find()方法
db.Where("name = ?", "jinzhu").Find(&users)
// 不等于
db.Where("name <> ?", "jinzhu").Find(&users)
// IN
db.Where("name IN (?)", []string{"jinzhu", "bgbiao.top"}).Find(&users)
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// Time
// select * from users where updated_at > '2020-03-06 00:00:00'
db.Where("updated_at > ?", lastWeek).Find(&users)
// BETWEEN
// select * from users where created_at between '2020-03-06 00:00:00' and '2020-03-14 00:00:00'
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
Не условие
// select * from users where name != 'bgbiao.top';
db.Not("name", "jinzhu").First(&user)
// Not In
// select * from users where name not in ("jinzhu","bgbiao.top");
db.Not("name", []string{"jinzhu", "bgbiao.top"}).Find(&users)
// 主键不在slice中的查询
// select * from users where id not in (1,2,3)
db.Not([]int64{1,2,3}).First(&user)
// select * from users;
db.Not([]int64{}).First(&user)
// 原生SQL
// select * from users where not(name = 'bgbiao.top');
db.Not("name = ?", "bgbiao.top").First(&user)
// struct方式查询
// select * from users where name != 'bgbiao.top'
db.Not(User{Name: "bgbiao.top"}).First(&user)
Или условие
// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
// Struct 方式
// SELECT * FROM users WHERE name = 'jinzhu' OR name = 'bgbiao.top';
db.Where("name = 'jinzhu'").Or(User{Name: "bgbiao.top"}).Find(&users)
// Map 方式
// SELECT * FROM users WHERE name = 'jinzhu' OR name = 'bgbiao.top';
db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "bgbiao.top"}).Find(&users)
FirstOrCreate
Получите первую совпадающую запись, в противном случае создайте новую запись на основе заданного условия (поддерживаются только условия структуры и карты)
// 未找到,就插入记录
if select * from users where name = 'non_existing') is null; insert into users(name) values("non_existing")
db.FirstOrCreate(&user, User{Name: "non_existing"})
// 找到
// select * from users where name = 'bgbiao.top'
db.Where(User{Name: "bgbiao.top"}).FirstOrCreate(&user)
## attrs参数:如果记录未找到,将使用参数创建 struct 和记录.
// 未找到(将条件前置,并将拆入数据填充到Attrs方法中)
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// 找到
db.Where(User{Name: "bgbiao.top"}).Attrs(User{Age: 30}).FirstOrCreate(&user)
## assgin参数: 不管记录是否找到,都将参数赋值给 struct 并保存至数据库
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
подзапрос
*gorm.expr
подзапрос
// SELECT * FROM "orders" WHERE "orders"."deleted_at" IS NULL AND (amount > (SELECT AVG(amount) FROM "orders" WHERE (state = 'paid')));
db.Where("amount > ?", DB.Table("orders").Select("AVG(amount)").Where("state = ?", "paid").QueryExpr()).Find(&orders)
Поле запроса
Обычно мы хотим выбрать только несколько полей для запроса, указать поля, которые вы хотите получить из базы данных, и все поля будут выбраны по умолчанию.
// SELECT name, age FROM users;
db.Select("name, age").Find(&users)
// SELECT name, age FROM users;
db.Select([]string{"name", "age"}).Find(&users)
// SELECT COALESCE(age,'42') FROM users;
db.Table("users").Select("COALESCE(age,?)", 42).Rows()
Порядок сортировки)
// SELECT * FROM users ORDER BY age desc, name;
db.Order("age desc, name").Find(&users)
// 多字段排序
// SELECT * FROM users ORDER BY age desc, name;
db.Order("age desc").Order("name").Find(&users)
// 覆盖排序
//
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
Ограничить вывод
// SELECT * FROM users LIMIT 3;
db.Limit(3).Find(&users)
// -1 取消 Limit 条件
// SELECT * FROM users LIMIT 10;
// SELECT * FROM users;
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
Подсчет статистики
// SELECT count(*) from USERS WHERE name = 'jinzhu' OR name = 'bgbiao.top';
db.Where("name = ?", "jinzhu").Or("name = ?", "bgbiao.top").Find(&users).Count(&count)
// select count(*) from users where name = 'bgbiao.top'
db.Model(&User{}).Where("name = ?", "bgbiao.top").Count(&count)
// SELECT count(*) FROM deleted_users;
db.Table("deleted_users").Count(&count)
// SELECT count( distinct(name) ) FROM deleted_users;
db.Table("deleted_users").Select("count(distinct(name))").Count(&count)
Группировка (группа и наличие)
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Rows()
for rows.Next() {
...
}
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Rows()
for rows.Next() {
...
}
type Result struct {
Date time.Time
Total int64
}
db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Scan(&results)
запрос на подключение
rows, err := db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Rows()
for rows.Next() {
...
}
db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)
// 多连接及参数
db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("credit_cards.number = ?", "411111111111").Find(&user)
срывать запрос
Pluck, запросите столбец в модели как切片
, если вы хотите запросить несколько столбцов, вы должны использоватьScan
.
var ages []int64
db.Find(&users).Pluck("age", &ages)
var names []string
db.Model(&User{}).Pluck("name", &names)
db.Table("deleted_users").Pluck("name", &names)
сканирование сканирование
type Result struct {
Name string
Age int
}
var result Result
db.Table("users").Select("name, age").Where("name = ?", "Antonio").Scan(&result)
// 原生 SQL
db.Raw("SELECT name, age FROM users WHERE name = ?", "Antonio").Scan(&result)
возобновить
Обновить все поля
注意:
save обновит все поля, даже если нет назначения
db.First(&user)
user.Name = "bgbiao.top"
user.Age = 100
// update users set name = 'bgbiao.top',age=100 where id = user.id
db.Save(&user)
Обновить измененные поля
использоватьUpdate
иUpdates
метод
// 更新单个属性,如果它有变化
// update users set name = 'hello' where id = user.id
db.Model(&user).Update("name", "hello")
// 根据给定的条件更新单个属性
// update users set name = 'hello' where active = true
db.Model(&user).Where("active = ?", true).Update("name", "hello")
// 使用 map 更新多个属性,只会更新其中有变化的属性
// update users set name = 'hello',age=18,actived=false where id = user.id
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// 使用 struct 更新多个属性,只会更新其中有变化且为非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})
// 警告:当使用 struct 更新时,GORM只会更新那些非零值的字段
// 对于下面的操作,不会发生任何更新,"", 0, false 都是其类型的零值
db.Model(&user).Updates(User{Name: "", Age: 0, Actived: false})
Обновить выбранные поля
Если вы хотите обновить или игнорировать некоторые поля, вы можете использоватьSelect
илиOmit
// update users set name = 'hello' where id = user.id;
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// Omit()方法用来忽略字段
// update users set age=18,actived=false where id = user.id
db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
Нет обновления хука
Вышеупомянутая операция обновления автоматически запуститBeforeUpdate
,AfterUpdate
метод, чтобы обновить что-то вродеUpdatedAt
поля сохраняют своиAssociations
, если вы не хотите вызывать эти методы, вы можете использоватьUpdateColumn
,UpdateColumns
// 更新单个属性,类似于 `Update`
// update users set name = 'hello' where id = user.id;
db.Model(&user).UpdateColumn("name", "hello")
// 更新多个属性,类似于 `Updates`
// update users set name = 'hello',age=18 where id = user.id;
db.Model(&user).UpdateColumns(User{Name: "hello", Age: 18})
Массовое обновление
注意:
При использовании обновления экземпляра структуры обновляются только поля с ненулевыми значениями, слабые элементы обновляют все поля, рекомендуется использовать карту
// update users set name = 'hello',age=18 where id in (10,11)
db.Table("users").Where("id IN (?)", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18})
// 使用 struct 更新时,只会更新非零值字段,若想更新所有字段,请使用map[string]interface{}
db.Model(User{}).Updates(User{Name: "hello", Age: 18})
// 使用 `RowsAffected` 获取更新记录总数
db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected
Вычислять выражения с помощью SQL
// update products set price = price*2+100 where id = product.id
DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100))
// update products set price = price*2+100 where id = product.id;
DB.Model(&product).Updates(map[string]interface{}{"price": gorm.Expr("price * ? + ?", 2, 100)})
// update products set quantity = quantity-1 where id = product.id;
DB.Model(&product).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
// update products set quantity = quantity -1 where id = product.id and quantity > 1
DB.Model(&product).Where("quantity > 1").UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
Удалить
Удалить запись
注意:
При удалении записи убедитесь, что поле первичного ключа имеет значение. GORM удалит запись с помощью первичного ключа. Если первичный ключ пуст, GORM удалит все записи модели.
// 删除现有记录
// delete from emails where id = email.id;
db.Delete(&email)
// 为删除 SQL 添加额外的 SQL 操作
// delete from emails where id = email.id OPTION (OPTIMIZE FOR UNKNOWN)
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
пакетное удаление
// delete from emails where email like '%jinzhu%'
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
// 同上
db.Delete(Email{}, "email LIKE ?", "%jinzhu%")
мягкое удаление
Если модель имеетDeletedAt
поле, он автоматически получит функцию мягкого удаления!
при звонкеDelete
метод, запись фактически не удаляется из базы данных, а толькоDeletedAt
Значение поля будет установлено на текущее время.
Раньше мы могли бы использоватьisDelete
поля, например, для пометки записей на удаление, но встроенные в гормDeletedAt
поле, и есть соответствующие крючки для обеспечения мягкого удаления.
// UPDATE users SET deleted_at="2020-03-13 10:23" WHERE id = user.id;
db.Delete(&user)
// 批量删除
// 软删除的批量删除其实就是把deleted_at改成当前时间,并且在查询时无法查到,所以底层用的是update的sql
db.Where("age = ?", 20).Delete(&User{})
// 查询记录时会忽略被软删除的记录
// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;
db.Where("age = 20").Find(&user)
// Unscoped 方法可以查询被软删除的记录
// SELECT * FROM users WHERE age = 20;
db.Unscoped().Where("age = 20").Find(&users)
физическое удаление
注意:
использоватьUnscoped().Delete()
Метод является реальным выполнением в sqldelete
утверждение.
// Unscoped 方法可以物理删除记录
// DELETE FROM orders WHERE id=10;
db.Unscoped().Delete(&order)
В этой статье используетсяmdniceнабор текста