1 基本使用
![GORM使用_第1张图片](http://img.e-com-net.com/image/info8/8393676934274c30945178dfca7f7f63.jpg)
![GORM使用_第2张图片](http://img.e-com-net.com/image/info8/66918f7c2314449a9d07e4a94c3d85fd.jpg)
1.1 连接数据库
func BasicUsage() {
dsn := "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
fmt.Println(db)
}
1.2 基于模型迁移表结构
![GORM使用_第3张图片](http://img.e-com-net.com/image/info8/0b7a720307744565bd253c2eeac2fbd8.jpg)
type Article struct {
gorm.Model
Subject string
Likes uint
Published bool
PublishTime time.Time
AuthorID uint
}
func BasicUsage() {
dsn := "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
if err := db.AutoMigrate(&Article{}); err != nil {
log.Fatal(err)
}
}
1.3 基本的crud
var DB *gorm.DB
func init() {
const dsn = "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
if err := db.AutoMigrate(&Article{}); err != nil {
log.Fatal(err)
}
DB = db
}
func Create() {
article := &Article{
Subject: "gorm 增操作",
Likes: 0,
Published: true,
PublishTime: time.Time{},
AuthorID: 2,
}
if err := DB.Create(article).Error; err != nil {
log.Fatal(err)
}
fmt.Println(article)
}
func Retrieve(id uint) {
article := &Article{}
if err := DB.First(article, id).Error; err != nil {
log.Fatal(err)
}
fmt.Println(article)
}
func Update() {
article := &Article{}
if err := DB.First(article, 1).Error; err != nil {
log.Fatal(err)
}
article.AuthorID = 23
article.Likes = 512
article.Subject = "新的文章标题"
if err := DB.Save(article).Error; err != nil {
log.Fatal(err)
}
}
func Delete() {
article := &Article{}
if err := DB.First(article, 2).Error; err != nil {
log.Fatal(err)
}
if err := DB.Delete(article).Error; err != nil {
log.Fatal(err)
}
}
1.4 debug 日志
![请添加图片描述](http://img.e-com-net.com/image/info8/58480f7ab9e54a10ae06f3677ff03f52.jpg)
func Debug() {
article := &Article{
Subject: "这是一条新插入的数据",
AuthorID: 50,
}
if err := DB.Create(article).Error; err != nil {
log.Fatal(err)
}
if err := DB.Debug().First(article, article.ID).Error; err != nil {
log.Fatal(err)
}
}
![GORM使用_第4张图片](http://img.e-com-net.com/image/info8/9123dd8486b44123b137751d24b86e61.jpg)
![GORM使用_第5张图片](http://img.e-com-net.com/image/info8/ca580c134e82400e8a238c70d209b66d.jpg)
var logWriter io.Writer
logWriter, _ = os.OpenFile("./sql.log", os.O_CREATE|os.O_APPEND, 0644)
customLogger := logger.New(log.New(logWriter, "\n", log.LstdFlags),
logger.Config{
SlowThreshold: 200 * time.Millisecond,
LogLevel: logger.Info,
IgnoreRecordNotFoundError: false,
Colorful: false,
})
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: customLogger,
})
![GORM使用_第6张图片](http://img.e-com-net.com/image/info8/068139f29aff499bb5e00a92d025f8ba.jpg)
2 模型定义
2.1 表名定义
![GORM使用_第7张图片](http://img.e-com-net.com/image/info8/4b89440cbe834fabaea03dc70c542786.jpg)
![GORM使用_第8张图片](http://img.e-com-net.com/image/info8/3f799937160745c3b24225b47c14fa4f.jpg)
![GORM使用_第9张图片](http://img.e-com-net.com/image/info8/caf4bc9c0a60444aa6eb2569c1a22baf.jpg)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: customLogger,
NamingStrategy: schema.NamingStrategy{
TablePrefix: "msb_",
SingularTable: true,
NameReplacer: nil,
NoLowerCase: false,
},
})
if err != nil {
log.Fatal(err)
}
![GORM使用_第10张图片](http://img.e-com-net.com/image/info8/241083aed7a14a9495e4c08204ef1d82.jpg)
![GORM使用_第11张图片](http://img.e-com-net.com/image/info8/a4812d3e20cd4331934d3ff6b6811ec8.jpg)
func Migrate() {
if err := DB.AutoMigrate(&Post{}, &Category{}, &PostCategory{}, &Box{}); err != nil {
log.Fatal(err)
}
}
![在这里插入图片描述](http://img.e-com-net.com/image/info8/48500991cbe9458cb938cfafca279cf7.jpg)
2.2 字段类型映射
![GORM使用_第12张图片](http://img.e-com-net.com/image/info8/d1fde77d22fb4c1086c6f1348da81aea.jpg)
2.3 指针类型与非指针类型区别
![GORM使用_第13张图片](http://img.e-com-net.com/image/info8/cacdb4b7d57d42348e43ee04bf349f5e.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/986a127f492d4d249dbc693bf8b96431.jpg)
- 若表中字段不为null,则使用T类型就够了 因为不存在例如(数据库中为null,对应到结构体中值为0,则0到底是不是有用的值)
2.4 自定义字段类型
![GORM使用_第14张图片](http://img.e-com-net.com/image/info8/b1a630cb63334aa3a5f8e48bbf8d2eba.jpg)
type CustomTypeModel struct {
gorm.Model
FTime time.Time
FNullTime sql.NullTime
Fstring string
FNullString sql.NullString
FUUID uuid.UUID
FNullUUID uuid.NullUUID
}
func CustomType() {
ctm := &CustomTypeModel{}
DB.AutoMigrate(ctm)
ctm.FTime = time.Time{}
ctm.FNullTime = sql.NullTime{}
ctm.Fstring = ""
ctm.FNullString = sql.NullString{}
ctm.FUUID = uuid.New()
ctm.FNullUUID = uuid.NullUUID{}
DB.Create(ctm)
DB.First(ctm, ctm.ID)
if ctm.Fstring == "" {
fmt.Println("FString is NULL")
} else {
fmt.Println("FString is NOT NULL")
}
if ctm.FNullString.Valid == false {
fmt.Println("FNullString is NULL")
} else {
fmt.Println("FNullString is NOT NULL")
}
}
2.5 字段标签设置字段属性
![GORM使用_第15张图片](http://img.e-com-net.com/image/info8/b550395fce9e4baf9cd71e672c9833e9.jpg)
type FieldTag struct {
gorm.Model
FStringDefault string `gorm:`
FTypeChar string `gorm:"type:char(32)"`
FTypeVarchar string `gorm:"type:varchar(255)"`
FTypeText string `gorm:"type:text"`
FTypeBlob []string `gorm:"type:blob"`
FTypeEnum string `gorm:"type:enum('GO','GORM','MySQL')"`
FTypeSet string `gorm:"type:set('GO','GORM','MySQL')"`
FColNum string `gorm:"column:cus tom_column_name"`
FColNotNull string `gorm:"type:varchar(255);not null"`
FColDefault string `gorm:"type:varchar(255);default: gorm middle ware;"`
FColComment string `gorm:"type:varchar(255);comment:带有注释的字段"`
}
2.6 索引和约束管理
![GORM使用_第16张图片](http://img.e-com-net.com/image/info8/6d5d37cd283e459da0e1cb7d3a868452.jpg)
![GORM使用_第17张图片](http://img.e-com-net.com/image/info8/859f08b6b1dd48f68d1cd74933db205e.jpg)
type IAndC struct {
ID uint `gorm:"primaryKey"`
Email string `gorm:"type:varchar(255);uniqueIndex"`
Age uint8 `gorm:"index;check:age >= 18 AND email is not null"`
FirstName string `gorm:"index:name"`
LastName string `gorm:"index:name"`
FirstName1 string `gorm:"index:name1,priority:2"`
LastName1 string `gorm:"index:name,priority:1"`
Height float32 `gorm:"index:,sort:desc"`
AddressHash string `gorm:"index:,length:12,comment:前12个字符作为索引关键字"`
}
2.7 字段操作控制
![GORM使用_第18张图片](http://img.e-com-net.com/image/info8/6e5c78feda96442189c6e29b63240fe1.jpg)
![GORM使用_第19张图片](http://img.e-com-net.com/image/info8/107be4f7154547c4b11cad361f75e239.jpg)
type Service struct {
gorm.Model
Url string `gorm:"-:migration"`
Schema string
Host string
Path string
QueryString string
}
2.8 序列化器的使用
![GORM使用_第20张图片](http://img.e-com-net.com/image/info8/874711cc1b604eb5a714c8f30aff8a50.jpg)
type Paper struct {
gorm.Model
Subject string
Tags []string `gorm:"serializer:json"`
}
func PaperCrud() {
err := DB.AutoMigrate(&Paper{})
if err != nil {
log.Fatal(err)
}
paper := &Paper{}
paper.Subject = "使用serializer操作Tags字段"
paper.Tags = []string{"GO", "Serializer", "Gorm", "MySQL"}
if err := DB.Create(paper).Error; err != nil {
log.Fatal(err)
}
newPaper := &Paper{}
DB.First(newPaper, 2)
fmt.Printf("%+v", newPaper)
}
2.9 自定义序列化器的实现
![GORM使用_第21张图片](http://img.e-com-net.com/image/info8/8a55300e8e474372bd22ea58985b5519.jpg)
![GORM使用_第22张图片](http://img.e-com-net.com/image/info8/7699d111687f491bacbdb83202c14dad.jpg)
type Paper struct {
gorm.Model
Subject string
Tags []string `gorm:"serializer:json"`
Categories []string `gorm:"serializer:csv"`
}
type CSVSerializer struct{}
func (CSVSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error {
var fieldValue []string
if dbValue != nil {
var str string
switch v := dbValue.(type) {
case string:
str = v
case []byte:
str = string(v)
default:
return fmt.Errorf("failed to unmarshal CSV value :%#v", dbValue)
}
fieldValue = strings.Split(str, ",")
}
field.ReflectValueOf(ctx, dst).Set(reflect.ValueOf(fieldValue))
return nil
}
func (CSVSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
return strings.Join(fieldValue.([]string), ","), nil
}
func CustomSerializer() {
schema.RegisterSerializer("csv", CSVSerializer{})
err := DB.AutoMigrate(&Paper{})
if err != nil {
log.Fatal(err)
}
paper := &Paper{}
paper.Subject = "使用自定义操作categories字段"
paper.Categories = []string{"GO", "Serializer", "Gorm", "MySQL", "categories "}
paper.Tags = []string{"GO", "Serializer", "Gorm", "MySQL"}
if err := DB.Create(paper).Error; err != nil {
log.Fatal(err)
}
newPaper := &Paper{}
DB.First(newPaper, paper.ID)
fmt.Printf("%+v", newPaper)
}
![在这里插入图片描述](http://img.e-com-net.com/image/info8/1140951cfc374bd58c416cb5383ded1e.jpg)
2.10 嵌入结构体和gorm.model
type Blog struct {
gorm.Model
BlogBasic
Author `gorm:"embeddedPrefix:au thor_"`
}
type BlogBasic struct {
Subject string
Summary string
Content string
}
type Author struct {
Name string
Email string
}
2.10 小节
![GORM使用_第23张图片](http://img.e-com-net.com/image/info8/8f61b9b4cd304af3b073173cd347cc2e.jpg)
3 具体操作
![GORM使用_第24张图片](http://img.e-com-net.com/image/info8/9f2f772132db4edd8c9dc7baba31147c.jpg)
![GORM使用_第25张图片](http://img.e-com-net.com/image/info8/786fc1187a3f4d5bafe169e4328f20d4.jpg)
3.1
3.2 错误处理
![GORM使用_第26张图片](http://img.e-com-net.com/image/info8/417c5200fb2e4a53b7b1417b873538c5.jpg)
![GORM使用_第27张图片](http://img.e-com-net.com/image/info8/1779efd579f14e66b2daae003792625c.jpg)
3.3 基于模型和map完成创建
![GORM使用_第28张图片](http://img.e-com-net.com/image/info8/cbdd52119d204c2ca7cd1e3bf10874fd.jpg)
![GORM使用_第29张图片](http://img.e-com-net.com/image/info8/d900479cd95a4cb388790ac731188946.jpg)
type Content struct {
gorm.Model
Subject string
Likes uint
PublishTime *time.Time
}
func CreateBasic() {
DB.AutoMigrate(&Content{})
c1 := Content{}
c1.Subject = "GORM的使用"
result := DB.Create(&c1)
if result.Error != nil {
log.Fatal(result.Error)
}
fmt.Println(c1.ID, result.RowsAffected)
values := map[string]any{
"Subject": "通过map指定的值",
"PublishTime": time.Now(),
}
result2 := DB.Model(&Content{}).Create(values)
if result2.Error != nil {
log.Fatal(result2.Error)
}
fmt.Println(result2.RowsAffected)
}
- 使用map 自动更新创建时间 不会随之添加,只会在记录中添加map中有的数据
![在这里插入图片描述](http://img.e-com-net.com/image/info8/987444bb84304db79c86d23d9905ed28.jpg)
3.4 批量插入
![请添加图片描述](http://img.e-com-net.com/image/info8/f17aa73849994b1e9feb15b8f248de3b.jpg)
func CreateMulti() {
DB.AutoMigrate(&Content{})
models := []Content{
{Subject: "标题1"},
{Subject: "标题2"},
{Subject: "标题3"},
{Subject: "标题3-1"},
}
result := DB.Create(&models)
if result.Error != nil {
log.Fatal(result.Error)
}
fmt.Println("RowsAffected:", result.RowsAffected)
for _, m := range models {
fmt.Println("ID:", m.ID)
}
vs := []map[string]any{
{"Subject": "标题4"},
{"Subject": "标题5"},
{"Subject": "标题6"},
{"Subject": "标题6-1"},
}
result2 := DB.Model(&Content{}).Create(vs)
if result2.Error != nil {
log.Fatal(result2.Error)
}
fmt.Println("ROWS:", result2.RowsAffected)
}}
![请添加图片描述](http://img.e-com-net.com/image/info8/53981bd7ebce41aa8d2f8c896002d0ef.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/ff53ce709425400c94d6aed2df8938cc.jpg)
func CreateBatches() {
DB.AutoMigrate(&Content{})
models := []Content{
{Subject: "标题11"},
{Subject: "标题12"},
{Subject: "标题13"},
{Subject: "标题14"},
}
result := DB.CreateInBatches(&models, 2)
if result.Error != nil {
log.Fatal(result.Error)
}
fmt.Println("RowsAffected:", result.RowsAffected)
for _, m := range models {
fmt.Println("ID:", m.ID)
}
vs := []map[string]any{
{"Subject": "标题15"},
{"Subject": "标题16"},
{"Subject": "标题17"},
{"Subject": "标题18"},
}
result2 := DB.Model(&Content{}).CreateInBatches(vs, 2)
if result2.Error != nil {
log.Fatal(result2.Error)
}
fmt.Println("ROWS:", result2.RowsAffected)
}
![GORM使用_第30张图片](http://img.e-com-net.com/image/info8/0d7a61bfdaad4129a2587d3710b6ca26.jpg)
3.5 UpSert更新插入
![GORM使用_第31张图片](http://img.e-com-net.com/image/info8/f6a90e3923924fd4a030dfd7a1400170.jpg)
func UpSert() {
DB.AutoMigrate(&Content{})
c1 := Content{}
c1.Subject = "新标题1111"
c1.Likes = 10
DB.Create(&c1)
c2 := Content{}
c2.ID = c1.ID
c2.Subject = "新标题*****"
c2.Likes = 200
DB.Create(&c1)
fmt.Println(c1)
if err := DB.
Clauses(clause.OnConflict{UpdateAll: true}).
Create(&c2).Error; err != nil {
log.Fatal(err)
}
c4 := Content{}
c4.ID = c1.ID
c4.Subject = "新标题456789"
c4.Likes = 300
if err := DB.Clauses(clause.OnConflict{DoUpdates: clause.AssignmentColumns(
[]string{"likes"})}).
Create(&c4).
Error; err != nil {
log.Fatal(err)
}
}
3.6 创建时默认值的处理
![GORM使用_第32张图片](http://img.e-com-net.com/image/info8/53aea57e3260469aa78e7a4caf4a014f.jpg)
type Content struct {
gorm.Model
Subject string
Likes uint `gorm:"default:99"`
Vikes *uint `gorm:"default:99"`
PublishTime *time.Time
}
func DefaultValue() {
DB.AutoMigrate(&Content{})
c1 := Content{}
c1.Subject = "新标题2222"
vlikes := uint(0)
c1.Vikes = &vlikes
DB.Create(&c1)
}
![在这里插入图片描述](http://img.e-com-net.com/image/info8/d943b9b70c884d03bf8653fb5d5b99c8.jpg)
![GORM使用_第33张图片](http://img.e-com-net.com/image/info8/8f595c7bb6284d499db6b7d4b1478e75.jpg)
3.7 创建时选择特定字段
![GORM使用_第34张图片](http://img.e-com-net.com/image/info8/68f3409d37014d90bcffdfa1e8fc368d.jpg)
func Omit() {
DB.AutoMigrate(&Content{})
c1 := Content{}
c1.Subject = "原始标题"
c1.Likes = 10
c1.Vikes = 99
now := time.Now()
c1.PublishTime = &now
DB.Select("Subject", "Likes", "UpdatedAt").Create(&c1)
DB.Omit("Subject", "UpdatedAt", "Vikes").Create(&c1)
}
3.8 创建时的钩子方法
![GORM使用_第35张图片](http://img.e-com-net.com/image/info8/3c588ba72cbf4147aa3e434d380510cc.jpg)
func (c *Content) BeforeCreate(db *gorm.DB) error {
if c.PublishTime == nil {
now := time.Now()
c.PublishTime = &now
}
db.Statement.AddClause(clause.OnConflict{UpdateAll: true})
return nil
}
![GORM使用_第36张图片](http://img.e-com-net.com/image/info8/27f8a54bd4234eb6b246ea5f331f292b.jpg)
![GORM使用_第37张图片](http://img.e-com-net.com/image/info8/3cbdfd992cbe477cb2ba75a23db3f6b2.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/8ab3967bacdb40b4845934f310a4cffa.jpg)
3.9 查询 基于主键的查询
![GORM使用_第38张图片](http://img.e-com-net.com/image/info8/c5d7c7266fd14d10ba5c0fea8169a595.jpg)
![GORM使用_第39张图片](http://img.e-com-net.com/image/info8/9a42bd073f774c0b896ff94d77c87367.jpg)
type Content struct {
gorm.Model
Subject string
Likes uint `gorm:`
Vikes uint `gorm:`
PublishTime *time.Time
}
type ContentStrPK struct {
ID string `gorm:"primaryKey"`
Subject string
Likes uint
Views uint
PublishTime *time.Time
}
func GetByPk() {
DB.AutoMigrate(&Content{}, &ContentStrPK{})
c := Content{}
if err := DB.First(&c, 10).Error; err != nil {
log.Println(err)
}
cStr := ContentStrPK{}
if err := DB.First(&cStr, "id = ?", "some pk").Error; err != nil {
log.Println(err)
}
var cs []Content
if err := DB.Find(&cs, []uint{10, 11, 12, 13}).Error; err != nil {
log.Println(err)
}
for _, v := range cs {
fmt.Println(v)
}
var cStrs []ContentStrPK
if err := DB.Find(&cStrs, "id IN ?", []string{"some", "key", "you"}).Error; err != nil {
log.Println(err)
}
}
3.10 查询单条
![GORM使用_第40张图片](http://img.e-com-net.com/image/info8/1b2543c86cfb4e3d89f1c6fac2a1b689.jpg)
func GetONE() {
c := Content{}
if err := DB.First(&c, "id > ?", 19).Error; err != nil {
log.Println(err)
}
fmt.Println("first ", c)
l := Content{}
if err := DB.Last(&l, "id > ?", 19).Error; err != nil {
log.Println(err)
}
fmt.Println("Last ", l)
t := Content{}
if err := DB.Take(&t, "id > ?", 19).Error; err != nil {
log.Println(err)
}
fmt.Println("Take ", t)
f := Content{}
if err := DB.Limit(1).Find(&f, "id > ?", 19).Error; err != nil {
fmt.Println(err)
}
fmt.Println("Limit Find ", f)
fs := Content{}
if err := DB.Find(&fs, "id > ?", 19).Error; err != nil {
fmt.Println(err)
}
fmt.Println("find ", fs)
}
3.11 查询结果扫描到Map类型
![GORM使用_第41张图片](http://img.e-com-net.com/image/info8/1c8a6c63fc57432abb51cc97768492f0.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/cdf0c917abdd46e981ea2c8deb095bad.jpg)
func GetToMap() {
c := map[string]any{}
if err := DB.Model(&Content{}).First(&c, 13).Error; err != nil {
log.Println(err)
}
fmt.Println(c["id"])
if c["id"].(uint) == 13 {
fmt.Println("BING GO!")
}
fmt.Println(c["created_at"])
t, err := time.Parse("2006-01-02 15:04:05.000 -0700 CST", "2023-08-24 20:46:20.372 +0800 CST")
if err != nil {
log.Println(err)
}
if c["created_at"].(time.Time) == t {
fmt.Println("created_at time bingo !")
}
var cs []map[string]any
if err := DB.Model(&Content{}).Find(&cs, []uint{18, 19, 20}).Error; err != nil {
fmt.Println(err)
}
for _, v := range cs {
fmt.Println(v["id"], v["subject"])
}
}
3.12 查询单列
![GORM使用_第42张图片](http://img.e-com-net.com/image/info8/66093670e3044bcfbccbbdf3c895388b.jpg)
func GetPluck() {
var subjects []sql.NullString
if err := DB.Model(Content{}).Pluck("subject", &subjects).Error; err != nil {
fmt.Println(err)
}
for _, v := range subjects {
if v.Valid {
fmt.Println(v.String)
} else if v.Valid == false {
fmt.Println("{NULL}", v.Valid)
}
}
}
func GetPluckExp() {
var subjects []string
if err := DB.Model(&Content{}).
Pluck("concat(coalesce(subject,'[no subject]'),'-',likes)", &subjects).Error; err != nil {
log.Println(err)
}
for _, v := range subjects {
fmt.Println(v)
}
}
3.13 字段选择子句
type Content struct {
gorm.Model
Subject string
Likes uint `gorm:`
Vikes uint `gorm:`
PublishTime *time.Time
Sv string `gorm:"-:migration;<-:false;"`
}
func GetSelect() {
var c Content
var cm map[string]any
if err := DB.Select("subject", "likes").First(&c, 13).Error; err != nil {
log.Fatalln(err)
}
if err := DB.Select("subject", "likes", "concat(subject,'-',vikes) AS sv").First(&c, 13).Error; err != nil {
log.Fatalln(err)
}
if err := DB.Model(&Content{}).Select("subject", "likes", "concat(subject,'-',vikes) AS sv").First(&cm, 13).Error; err != nil {
log.Fatalln(err)
}
fmt.Printf("%+v\n", cm)
}
3.14 去重选项distinct
![GORM使用_第43张图片](http://img.e-com-net.com/image/info8/8a276c8b55384fc3b895dc16ad77a2e1.jpg)
func GetDistinct() {
var cs []Content
if err := DB.Distinct("subject").Find(&cs).Error; err != nil {
log.Fatalln(err)
}
for _, v := range cs {
fmt.Printf("%+v\n", v.Subject)
}
}
3.15 条件设置方法
![GORM使用_第44张图片](http://img.e-com-net.com/image/info8/c6bd1ca21ef34824ab79b4006bc80b7d.jpg)
func WhereMethod() {
var cs []Content
if err := DB.Find(&cs, "likes > ? AND subject like ?", 90, "新标题%").Error; err != nil {
log.Fatalln(err)
}
if err := DB.Where("likes > ? AND subject like ?", 90, "新标题%").Find(&cs).Error; err != nil {
log.Fatalln(err)
}
query := DB.Where("likes > ?", 90)
subject := "123"
if subject != "" {
query.Where("subject like ?", "新标题%")
}
query = DB.Where("likes > ?", 90)
subject = "新标题"
if subject != "" {
query.Or("subject like ?", subject+"%")
}
query = DB.Where("likes > ?", 90)
subject = "新标题"
if subject != "" {
query.Not("subject like ?", subject+"%")
query.Or(DB.Not("subject like ?", subject+"%"))
}
if err := query.Find(&cs).Error; err != nil {
log.Fatalln(err)
}
}
3.16 条件语法规则
![GORM使用_第45张图片](http://img.e-com-net.com/image/info8/780d98b892c94ec78cee5538b069e4d9.jpg)
func WhereType() {
var cs []Content
condA := DB.Where("subject < ?", 1).Or("subject > ?", 2)
condB := DB.Where("subject < ?", 3).Where(DB.Where("subject < ?", 4).Or("subject < ?", 5))
query := DB.Where(condA).Where(condB)
query = DB.Where(map[string]any{
"views": 100,
"id": []uint{1, 2, 3, 4, 5},
})
query = DB.Where(Content{
Subject: "GORM",
Vikes: 100,
})
if err := query.Find(&cs).Error; err != nil {
log.Fatalln(err)
}
}
![GORM使用_第46张图片](http://img.e-com-net.com/image/info8/36ad7849deb94f1d82e13afafe572120.jpg)
func PlaceHolder() {
var cs []Content
query := DB.Where("likes = ? AND subject like ?", 100, "gorm%")
query = DB.Where("likes = @like AND subject like @subject",
sql.Named("subject", "gorm%"), sql.Named("like", 100))
query = DB.Where("likes = @like AND subject like @subject",
map[string]any{
"subject": "gorm%",
"like": 100,
})
if err := query.Find(&cs).Error; err != nil {
log.Fatalln(err)
}
}
3.17 字段排序和表达式排序
![GORM使用_第47张图片](http://img.e-com-net.com/image/info8/4fea0129d6904ba7ad343cb6ec0da7b0.jpg)
func OrderBy() {
var cs []Content
ids := []uint{2, 3, 1}
query := DB.Order("FIELD(id,2,3,1)")
query = DB.Clauses(clause.OrderBy{
Expression: clause.Expr{
SQL: "FIELD(id,?)",
Vars: []any{ids},
WithoutParentheses: true,
},
})
if err := query.Find(&cs, ids).Error; err != nil {
log.Fatalln(err)
}
for _, c := range cs {
fmt.Println(c.ID)
}
}
3.18 结果限定及分页
![GORM使用_第48张图片](http://img.e-com-net.com/image/info8/17e70b3c16e540009d9592482a442915.jpg)
const (
DefaultPage = 1
DefaultPageSize = 12
)
type Pager struct {
Page, PageSize int
}
func Pagination(pager Pager) {
page := DefaultPage
if pager.Page != 0 {
page = pager.Page
}
pagesize := DefaultPageSize
if pager.PageSize != 0 {
pagesize = pager.PageSize
}
offset := pagesize * (page - 1)
var cs []Content
if err := DB.Offset(offset).Limit(pagesize).Find(&cs); err != nil {
log.Println(err)
}
for _, v := range cs {
fmt.Println(v.ID)
}
}
![GORM使用_第49张图片](http://img.e-com-net.com/image/info8/da93f153dbdf43b8a6daa415a2a0d5e0.jpg)
func Paginate(pager Pager) func(db *gorm.DB) *gorm.DB {
page := DefaultPage
if pager.Page != 0 {
page = pager.Page
}
pagesize := DefaultPageSize
if pager.PageSize != 0 {
pagesize = pager.PageSize
}
offset := pagesize * (page - 1)
return func(db *gorm.DB) *gorm.DB {
return db.Offset(offset).Limit(pagesize)
}
}
func PaginationScope(pager Pager) {
var cs []Content
if err := DB.Scopes(Paginate(pager)).Find(&cs).Error; err != nil {
log.Println(err)
}
for _, v := range cs {
fmt.Println(v.ID)
}
}
3.19 分组聚合过滤
![GORM使用_第50张图片](http://img.e-com-net.com/image/info8/7a3991dac6db4032bb23439d89e1c425.jpg)
func GroupHaving() {
DB.AutoMigrate(&Content{})
type Result struct {
AuthorID uint
TotalViews int
TotalLikes int
AvgViews float64
}
var re []Result
if err := DB.Model(&Content{}).
Select("author_id", "SUM(vikes) as total_views", "SUM(likes) as total_likes", "AVG(vikes) as avg_views").
Group("author_id").Having("total_views > ?", 99).
Find(&re).Error; err != nil {
log.Fatalln(err)
}
}
3.20 count合计
![GORM使用_第51张图片](http://img.e-com-net.com/image/info8/bb093c00098542a9a53bae8917a3e2cf.jpg)
func Count(pager Pager) {
query := DB.Model(&Content{}).
Where("likes > ?", 99)
var count int64
if err := query.Count(&count).Error; err != nil {
log.Fatalln(err)
}
var cs []Content
if err := query.Scopes(Paginate(pager)).Find(&cs).Error; err != nil {
log.Println(err)
}
for _, v := range cs {
fmt.Println(v.ID)
}
}
3.21 迭代查询
![GORM使用_第52张图片](http://img.e-com-net.com/image/info8/437d0a4077014b189dbba3ed3df83b2c.jpg)
func Iterator() {
rows, err := DB.Model(&Content{}).Rows()
if err != nil {
log.Fatalln(err)
}
defer func() {
_ = rows.Close()
}()
for rows.Next() {
var c Content
if err := DB.ScanRows(rows, &c); err != nil {
log.Fatalln(err)
}
fmt.Println(c.Subject)
}
}
3.22 锁子句
![GORM使用_第53张图片](http://img.e-com-net.com/image/info8/b0d2952422b24960a2e376995ae0140f.jpg)
func Locking() {
var cs []Content
if err := DB.
Clauses(clause.Locking{Strength: "UPDATE"}).
Find(&cs).Error; err != nil {
log.Fatalln(err)
}
if err := DB.
Clauses(clause.Locking{Strength: "SHARE"}).
Find(&cs).Error; err != nil {
log.Fatalln(err)
}
}
3.23 子查询
![GORM使用_第54张图片](http://img.e-com-net.com/image/info8/4868bb1730d342ed845b618ac937db7a.jpg)
func SubQuery() {
DB.AutoMigrate(&Author{}, &Content{})
whereSubQuery := DB.Model(&Author{}).Select("id").Where("status = ?", 0)
var cs []Content
if err := DB.Where("author_id IN (?)", whereSubQuery).Find(&cs).Error; err != nil {
log.Fatalln(err)
}
fromSubQuery := DB.Model(&Content{}).Select("subject", "likes").Where("publish_time IS NULL")
type Result struct {
Subject string
Likes int
}
var rs []Result
if err := DB.Table("(?) AS temp", fromSubQuery).
Where("likes > ?", 10).
Find(&rs).Error; err != nil {
log.Fatalln(err)
}
}
3.24 钩子方法 查询钩子
![GORM使用_第55张图片](http://img.e-com-net.com/image/info8/bdcbca9b10aa4140b19f432350d0c6b4.jpg)
func (c *Content) AfterFind(db *gorm.DB) error {
if c.AuthorID == 0 {
c.AuthorID = 1
}
return nil
}
func FindHook() {
var c Content
if err := DB.First(&c, 13).Error; err != nil {
log.Fatalln(err)
}
fmt.Printf("%+v\n", c)
}
- AuthorID值赋为1
![在这里插入图片描述](http://img.e-com-net.com/image/info8/8ebd0c8c6a254dd7811dd6930392e53f.jpg)
3.25 更新-主键条件更新及获取更新记录数
![GORM使用_第56张图片](http://img.e-com-net.com/image/info8/fa05c3b3e6a54946af58a71a1bcfcf41.jpg)
func UpdatePK() {
var c Content
if err := DB.Save(&c).Error; err != nil {
log.Fatalln(err)
}
fmt.Println("1:", c.ID)
if err := DB.Save(&c).Error; err != nil {
log.Fatalln(err)
}
fmt.Println("2:", c.ID)
}
![请添加图片描述](http://img.e-com-net.com/image/info8/50df6ef1915741daa70ce6f67b76006d.jpg)
![GORM使用_第57张图片](http://img.e-com-net.com/image/info8/930184af44894ec88fee4a490fb77d03.jpg)
func UpdateWhere() {
values := map[string]any{
"subject": "Where Update Row",
"likes": 10001,
}
result := DB.Model(&Content{}).
Omit("updated_at").
Where("likes > ?", 100).
Updates(values)
if result.Error != nil {
log.Fatalln(result.Error)
}
log.Println("updated rows num: ", result.RowsAffected)
}
![GORM使用_第58张图片](http://img.e-com-net.com/image/info8/96d82a2205f44bf1a2c25a3c4357d6e3.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/e03254ab47cd4c868f5e6ba3efa6d8fc.jpg)
![GORM使用_第59张图片](http://img.e-com-net.com/image/info8/23a25a7d7d9f4e79a2d92b70042bda49.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/8b1278f2c32044be93271b0bddd765c7.jpg)
func UpdateNOWhere() {
values := map[string]any{
"subject": "Where Update Row",
"likes": 101,
}
result := DB.Model(&Content{}).
Omit("updated_at").
Where("1").
Updates(values)
if result.Error != nil {
log.Fatalln(result.Error)
}
log.Println("updated rows num: ", result.RowsAffected)
}
3.26 更新-表达式值
![请添加图片描述](http://img.e-com-net.com/image/info8/a3e5526c29764c79a27ec38318698f95.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/414b1df5102b4318823c4458158df8ea.jpg)
func UpdateExpr() {
values := map[string]any{
"subject": "Where Update Row",
"likes": gorm.Expr("likes + ?", 10),
}
result := DB.Model(&Content{}).
Omit("updated_at").
Where("likes > ?", 100).
Updates(values)
if result.Error != nil {
log.Fatalln(result.Error)
}
log.Println("updated rows num: ", result.RowsAffected)
}
3.27 更新-Hook简单介绍
![GORM使用_第60张图片](http://img.e-com-net.com/image/info8/b70c41e50ca54a12bd4fd03f159348ea.jpg)
3.28 删除-基本主键条件删除操作
![GORM使用_第61张图片](http://img.e-com-net.com/image/info8/50534647c9fa499ea0a8c67f7f961aba.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/a3c888c54a3549e497fca51b63232979.jpg)
func DeleteWhere() {
result1 := DB.Delete(&Content{}, "likes < ?", 100)
if err := result1.Error; err != nil {
log.Fatalln(result1.Error)
}
result2 := DB.Where("likes < ?", 100).Delete(&Content{})
if err := result2.Error; err != nil {
log.Fatalln(err)
}
}
![GORM使用_第62张图片](http://img.e-com-net.com/image/info8/2c9494f4df9e41b99f6c3ab572f6837d.jpg)
3.29 删除-软删除和永久删除
![GORM使用_第63张图片](http://img.e-com-net.com/image/info8/be0d81285d7a414386826c50fb1b3008.jpg)
![GORM使用_第64张图片](http://img.e-com-net.com/image/info8/6fa56a4148be418d9aa6fdaa4e14aac4.jpg)
![请添加图片描述](http://img.e-com-net.com/image/info8/7a9ea967a7c2404783dd4a003a51df17.jpg)
func FindDeleted() {
var c Content
DB.Delete(&c, 13)
if err := DB.Unscoped().First(&c, 13).Error; err != nil {
log.Fatalln(err)
}
fmt.Println("unscoped:", c)
}
![GORM使用_第65张图片](http://img.e-com-net.com/image/info8/fb3104e724fb45d0b4719f509d2e095d.jpg)
func DeleteHard() {
var c Content
if err := DB.Unscoped().Delete(&c, 14).Error; err != nil {
log.Fatalln(err)
}
}
3.30 原生sql的执行和结果处理
![GORM使用_第66张图片](http://img.e-com-net.com/image/info8/5c64ee11eca747efa7609042a002ac3b.jpg)
func RawSelect() {
type Result struct {
ID uint
Subject string
Likes, Vikes int
}
var rs []Result
sql := "SELECT `id`,`subject`,`likes`,`vikes` FROM `msb_content` WHERE `likes` > ? ORDER BY `likes` DESC LIMIT ?"
if err := DB.Raw(sql, 99, 12).Scan(&rs).Error; err != nil {
log.Fatalln(err)
}
log.Println(rs)
}
func RawExec() {
sql := "UPDATE `msb_content` SET `subject` = CONCAT(`subject`,'-new postfix') WHERE `id` BETWEEN ? AND ?"
result := DB.Exec(sql, 20, 30)
if result.Error != nil {
log.Fatalln(result.Error)
}
log.Println(result.RowsAffected)
}
![GORM使用_第67张图片](http://img.e-com-net.com/image/info8/d050d3b7038f4d349fa4f8320963491a.jpg)
func RowAndRows() {
sql := "SELECT `id`,`subject`,`likes`,`vikes` FROM `msb_content` WHERE `likes` > ? ORDER BY `likes` DESC LIMIT ?"
rows, err := DB.Raw(sql, 99, 12).Rows()
if err != nil {
log.Fatalln(err)
}
for rows.Next() {
type Result struct {
ID uint
Subject string
Likes, Vikes int
}
var r Result
DB.ScanRows(rows, &r)
fmt.Println(r)
}
}
3.31 会话模式的基本使用
![请添加图片描述](http://img.e-com-net.com/image/info8/e3c2a366a65242deb8efaf1852d056d6.jpg)
func SessionIssue() {
db := DB.Model(&Content{}).Where("vikes > ?", 100)
db.Where("likes > ?", 99)
var cs []Content
db.Find(&cs)
}
![GORM使用_第68张图片](http://img.e-com-net.com/image/info8/9f481fb6b5d940bcadc1cbfa660957cb.jpg)
func SessionNew() {
db := DB.Model(&Content{}).Where("vikes > ?", 100).Session(&gorm.Session{})
var cs1 []Content
db.Where("likes > ?", 9).Find(&cs1)
var cs2 []Content
db.Where("likes > ?", 99).Find(&cs2)
}
3.32 会话模式的常用实操选项
![GORM使用_第69张图片](http://img.e-com-net.com/image/info8/e48e513158fd409ba8f2b1c6da57cdaf.jpg)
![GORM使用_第70张图片](http://img.e-com-net.com/image/info8/200e6ee67cae4abab2c39b82d88c4a51.jpg)
![GORM使用_第71张图片](http://img.e-com-net.com/image/info8/510c2622f3b24515be1703e919a18c7f.jpg)
![GORM使用_第72张图片](http://img.e-com-net.com/image/info8/44b5578d89b5432f810c1e481702c966.jpg)
![GORM使用_第73张图片](http://img.e-com-net.com/image/info8/54f10c8ba0a5424db91a726a3cb8d9fc.jpg)
func SessionOptions() {
db:=DB.Session(&gorm.Session{
SkipHooks:true,
})
db.Save(&Content{Subject: "no create hook"})
db := DB.Session(&gorm.Session{
DryRun: true,
})
stmt := db.Save(&Content{}).Statement
fmt.Println(stmt.SQL.String())
fmt.Println(stmt.Vars)
db := DB.Session(&gorm.Session{
PrepareStmt: true,
})
}
3.33 context上下文支持
![GORM使用_第74张图片](http://img.e-com-net.com/image/info8/61a0cc4716c6415d8d1fd354d169335d.jpg)
func ContextTimeoutCancel() {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
defer cancel()
var cs []Content
if err := DB.WithContext(ctx).Limit(5).Find(&cs).Error; err != nil {
log.Fatalln(err)
}
fmt.Println(cs)
}