栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

go 语言Gin框架修改结构体字段为空值的解决办法

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

go 语言Gin框架修改结构体字段为空值的解决办法

在实际业务中,我们有可能把非空值更新为空值,当使用结构体更新的时候,GORM 只会更新那些非空的字段

例如下面的更新,没有东西会被更新,因为像 "", 0, false 是这些字段类型的空值

db.Model(&user).Updates(User{Address: "", Age: 0})

解决办法,修改源码:

1、通过引入一个标记:FORCE ,如果有该标记,则该字段IsBlank设置为false,

找到 scope.go文件,路径:

修改Fields方法

func (scope *Scope) Fields() []*Field {
	if scope.fields == nil {
		var (
			fields             []*Field
			indirectScopeValue = scope.IndirectValue()
			isStruct           = indirectScopeValue.Kind() == reflect.Struct
		)

		for _, structField := range scope.GetModelStruct().StructFields {
			if isStruct {
				fieldValue := indirectScopeValue
				for _, name := range structField.Names {
					if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
						fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
					}
					fieldValue = reflect.Indirect(fieldValue).FieldByName(name)
				}
                // 注释掉原来的
				// fields = append(fields, &Field{StructField: structField, Field: fieldValue, IsBlank: isBlank(fieldValue)})
				//有force代表强制更新
				_, ok := structField.TagSettingsGet("FORCE")
				fields = append(fields, &Field{StructField: structField, Field: fieldValue, IsBlank: isBlank(fieldValue) && !ok})
				//如果不是struct,则返回空,因为原生没有字段这个说法
			} else {
				fields = append(fields, &Field{StructField: structField, IsBlank: true})
			}
		}
		scope.fields = &fields
	}

	return *scope.fields
}

2、在结构体中加入标记

type User struct {
  gorm.Model
  Name        string
  Age          sql.NullInt64
  Address      string  `gorm:"index:addr;force:force;"` // 给Address 添加一个标记force
}

3、此时我们可以发现,Address为空值的时候可以更新。

但是当我们使用结构体查询的时候,默认查询这些字段的非零值,而我们添加了force标记是没有将空值的过滤掉,例如:

db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)

// 实际的sql为:

// SELECT * FROM users WHERe name = "jinzhu" AND age = 20 AND  Address="";

这显然不是我们想要的结果。。

4、所以我们需要再引入一个标记:REQUIRED。然后修改main.go中Update方法。遍历结构体字段,当查询到有REQUIRED标记的时候,动态将FORCE标记设置进去,从而避免了使用结构体查询的时候没有过滤空值

main.go路径:

修改Update方法:

func (s *DB) Update(attrs ...interface{}) *DB {
	scope := s.NewScope(s.Value)
	var indirectScopeValue = scope.IndirectValue()
	var isStruct = indirectScopeValue.Kind() == reflect.Struct
	for _, structField := range scope.GetModelStruct().StructFields {
		if isStruct {
			//有REQUIRED代表强制更新
			
			val, ok := structField.TagSettingsGet("REQUIRED")
			
			if ok && val == "false" {
				structField.TagSettingsSet("FORCE", "force")
			}
			defer structField.TagSettingsDelete("FORCE")
		}
	}
	return s.Updates(toSearchableMap(attrs...), true)
}

5、结构体添加required标记:

type User struct {

  gorm.Model
  Name        string
  Age          sql.NullInt64
  Address      string  `gorm:"index:addr;required:false;"` // 给Address 添加一个标记required

}

查询的时候过滤了空值:

db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
// 实际的sql为:
// SELECT * FROM users WHERe name = "jinzhu" AND age = 20;

更新的时候,

db.Model(&user).Updates(User{Address: ""})
// 实际sql为
// UPDATE user SET Address='' WHERe id=111

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/909909.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号