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

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

在实际业务中,我们有可能把非空值更新为空值,当使用结构体更新的时候,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

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/996185.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存