Gorm更新零值问题解决思路与过程

 更新时间:2023年01月12日 09:23:21   作者:Ch3n  
这篇文章主要介绍了Gorm更新零值问题解决思路与过程,总的来说这并不是一道难题,那为什么要拿出这道题介绍?拿出这道题真正想要传达的是解题的思路,以及不断优化探寻最优解的过程。希望通过这道题能给你带来一种解题优化的思路

一、前言

为方便描述教程例子,这里给出mysql表结构定义和golang结构体定义。

下面是教程用到的foods表结构定义:

CREATE TABLE `foods` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品id',
  `title` varchar(100) NOT NULL COMMENT '商品名',
  `price` float DEFAULT '0' COMMENT '商品价格',
  `stock` int(11) DEFAULT '0' COMMENT '商品库存',
  `type` int(11) DEFAULT '0' COMMENT '商品类型',
  `create_time` datetime NOT NULL COMMENT '商品创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

下面是foods表对应的golang结构体类型

//商品
type Food struct {
	Id         int
	Title      string
	Price      float32
	Stock      int
	Type       int
	//mysql datetime, date类型字段,可以和golang time.Time类型绑定, 详细说明请参考:gorm连接数据库章节。
	CreateTime time.Time
}
//为Food绑定表名
func (v Food) TableName() string {
	return "foods"
}

二、gorm更新记录常用方法

1. Save

用于保存模型变量的值。

提示: 相当于根据主键id,更新所有模型字段值。

food := Food{}
//先查询一条记录, 保存在模型变量food
//等价于: SELECT * FROM `foods`  WHERE (id = '2') LIMIT 1
db.Where("id = ?", 2).Take(&food)
//修改food模型的值
food.Price = 100
//等价于: UPDATE `foods` SET `title` = '可乐', `type` = '0', `price` = '100', `stock` = '26', `create_time` = '2018-11-06 11:12:04'  WHERE `foods`.`id` = '2'
db.Save(&food)

2. Update

更新单个字段值

//例子1:
//更新food模型对应的表记录
//等价于: UPDATE `foods` SET `price` = '25'  WHERE `foods`.`id` = '2'
db.Model(&food).Update("price", 25)
//通过food模型的主键id的值作为where条件,更新price字段值。
//例子2:
//上面的例子只是更新一条记录,如果我们要更全部记录怎么办?
//等价于: UPDATE `foods` SET `price` = '25'
db.Model(Food{}).Update("price", 25)
//注意这里的Model参数,使用的是Food{},新生成一个空白的模型变量,没有绑定任何记录。
//因为Food{}的id为空,gorm库就不会以id作为条件,where语句就是空的
//例子3:
//根据自定义条件更新记录,而不是根据主键id
//等价于: UPDATE `foods` SET `price` = '25'  WHERE (create_time > '2018-11-06 20:00:00')
db.Model(Food{}).Where("create_time > ?", "2018-11-06 20:00:00").Update("price", 25)

3. Updates

更新多个字段值

//例子1:
//通过结构体变量设置更新字段
updataFood := Food{
		Price:120,
		Title:"柠檬雪碧",
	}
//根据food模型更新数据库记录
//等价于: UPDATE `foods` SET `price` = '120', `title` = '柠檬雪碧'  WHERE `foods`.`id` = '2'
//Updates会忽略掉updataFood结构体变量的零值字段, 所以生成的sql语句只有price和title字段。
db.Model(&food).Updates(&updataFood)
//例子2:
//根据自定义条件更新记录,而不是根据模型id
updataFood := Food{
		Stock:120,
		Title:"柠檬雪碧",
	}
//设置Where条件,Model参数绑定一个空的模型变量
//等价于: UPDATE `foods` SET `stock` = '120', `title` = '柠檬雪碧'  WHERE (price > '10')
db.Model(Food{}).Where("price > ?", 10).Updates(&updataFood)
//例子3:
//如果想更新所有字段值,包括零值,就是不想忽略掉空值字段怎么办?
//使用map类型,替代上面的结构体变量
//定义map类型,key为字符串,value为interface{}类型,方便保存任意值
data := make(map[string]interface{})
data["stock"] = 0 //零值字段
data["price"] = 35
//等价于: UPDATE `foods` SET `price` = '35', `stock` = '0'  WHERE (id = '2')
db.Model(Food{}).Where("id = ?", 2).Updates(data)

提示: 通过结构体变量更新字段值, gorm库会忽略零值字段。就是字段值等于0, nil, “”, false这些值会被忽略掉,不会更新。如果想更新零值,可以使用map类型替代结构体。

4. 更新表达式

UPDATE foods SET stock = stock + 1 WHERE id = '2'

这样的带计算表达式的更新语句gorm怎么写?

gorm提供了Expr函数用于设置表达式

//等价于: UPDATE `foods` SET `stock` = stock + 1  WHERE `foods`.`id` = '2'
db.Model(&food).Update("stock", gorm.Expr("stock + 1"))

三、使用struct更新仅适用于非零值

user:=User{
	Name:"",
	Age:0,
	Actived:false,
}
db.Model(&user).Updates(user)
//此时不会更新这些零值,如需更新零值使用map
userMap:=map[string]interface{}{
  "name":"",
  "age":0,
  "actived":0,
}
db.Model(&user).Updates(userMap)

到此这篇关于Gorm更新零值问题解决思路与过程的文章就介绍到这了,更多相关Gorm更新零值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • golang连接redis库及基本操作示例过程

    golang连接redis库及基本操作示例过程

    这篇文章主要介绍了golang连接redis库及基本操作示例过程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • go doudou开发单体RESTful服务快速上手教程

    go doudou开发单体RESTful服务快速上手教程

    这篇文章主要为大家介绍了go doudou开发单体RESTful服务快速上手教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 详解Golang如何实现支持随机删除元素的堆

    详解Golang如何实现支持随机删除元素的堆

    堆是一种非常常用的数据结构,它能够支持在O(1)的时间复杂度获取到最大值(或最小值)。本文主要介绍了如何实现支持O(log(n))随机删除元素的堆,需要的可以参考一下
    2022-09-09
  • Golang基于sync.Once实现单例的操作代码

    Golang基于sync.Once实现单例的操作代码

    这篇文章主要介绍了golang实现单例的操作代码,本文介绍基于sync.Once的方式来实现单例,熟练掌握这种模式,并理解其底层原理,对大部分人来讲已经完全够用了,需要的朋友可以参考下
    2022-10-10
  • Go结构体从基础到应用深度探索

    Go结构体从基础到应用深度探索

    本文深入探讨了结构体的定义、类型、字面量表示和使用方法,旨在为读者呈现Go结构体的全面视角,通过结构体,开发者可以实现更加模块化、高效的代码设计,这篇文章旨在为您提供关于结构体的深入理解,助您更好地利用Go语言的强大功能
    2023-10-10
  • go语言单元测试基准测试及表驱动测试示例详解

    go语言单元测试基准测试及表驱动测试示例详解

    这篇文章主要为大家介绍了go语言单元测试基准测试及表驱动测试示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Go Interface接口初学者手册

    Go Interface接口初学者手册

    这篇文章主要为大家介绍了Go Interface接口的基础用法实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • go语言 http模型reactor示例详解

    go语言 http模型reactor示例详解

    这篇文章主要介绍了go语言 http模型reactor,接下来看一段基于reactor的示例,这里运行通过 go run main.go,本文结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • Bililive-go 实现直播自动监控录制功能

    Bililive-go 实现直播自动监控录制功能

    最近有直播录制的需求,但是自己手动录制太麻烦繁琐,于是用了开源项目Bililive-go进行全自动监控录制,对Bililive-go 直播自动监控录制实现思路感兴趣的朋友,一起看看吧
    2024-03-03
  • go+redis实现消息队列发布与订阅的详细过程

    go+redis实现消息队列发布与订阅的详细过程

    这篇文章主要介绍了go+redis实现消息队列发布与订阅,redis做消息队列的缺点:没有持久化,一旦消息没有人消费,积累到一定程度后就会丢失,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09

最新评论