SoFunction
Updated on 2025-03-05

Gorm in Golang cannot update field to empty value

When using gorm to update a field to empty, it is found that it does not take effect and does not understand the specific reason. Therefore, you need to turn on debug mode to see how native SQL is executed.

type Student struct {
    Model
    Email       string  `form:"email" json:"email"`
    Name         string    `form:"name"  json:"name"`
}
func(c *Content) update(content Content) (err) {
    err = (&Content{}).Debug().Where("id = ?", 123).Update(&content).Error
}

Check the log to know that if the name is an empty string at this time, then the update SQL statement will not set. After checking, you will know that Gorm believes that it does not need to be processed for data such as null characters and 0, so. . .

When encountering this problem, there are two solutions:

A. Specify it through map when updating the value;

B. Modify the source code package of gorm to enable customization of whether it can be set to null value;

The first of the above two solutions is relatively simple, but it feels relatively low, so I chose to try the second one.

Of course, the second type also has its problems. For example, after being updated, you have to manually adjust it.

The following will focus on the implementation of the second plan.

1. Find the file under the gorm package

func convertInterfaceToMap(values interface{}, withIgnoredField bool, db *DB) map[string]interface{} {
    var attrs = map[string]interface{}{}
    switch value := values.(type) {
    case map[string]interface{}:
        return value
    case []interface{}:
        for _, v := range value {
            for key, value := range convertInterfaceToMap(v, withIgnoredField, db) {
                attrs[key] = value
            }
        }
    case interface{}:
        reflectValue := (values)
        switch () {
        case :
            for _, key := range () {
                attrs[ToColumnName(().(string))] = (key).Interface()
            }
        default:
            for _, field := range (&Scope{Value: values, db: db}).Fields() {
                if ! && (withIgnoredField || !) {
                    attrs[] = ()
                }
            }
        }
    }
    return attrs
}

The above code indicates that the data we pass will be converted to map type, and then the database field update will be updated. This code is very simple, which is to save the meet the conditions to map.

What we want to solve is that null values ​​can be updated, then they can be associated with them, and then find the next method;

// Fields get value's fields
func (scope *Scope) Fields() []*Field {
    if  == nil {
        var (
            fields             []*Field
            indirectScopeValue = ()
            isStruct           = () == 
        )
        for _, structField := range ().StructFields {
            if isStruct {
                fieldValue := indirectScopeValue
                for _, name := range  {
                    if () ==  && () {
                        ((().Elem()))
                    }
                    fieldValue = (fieldValue).FieldByName(name)
                }
                //Judge whether there is a force field in the model. Force is used here because when parsing the tag, it is converted to capitalization.                _, ok := ("FORCE")
                // If the field is empty and the field exists, set to false                fields = append(fields, &Field{StructField: structField, Field: fieldValue, IsBlank: isBlank(fieldValue) && !ok})
            } else {
                fields = append(fields, &Field{StructField: structField, IsBlank: true})
            }
        }
         = &fields
    }
    return *
}

Pay attention to the two lines with comments above, so I won’t repeat the function.

2. Modify our model

type Student struct {
    Model
    Email       string  `gorm:"force" form:"email" json:"email"`
    Name         string    `gorm:"force" form:"name"  json:"name"`
}
func(c *Content) update(content Content) (err) {
    err = (&Content{}).Debug().Where("id = ?", 123).Update(&content).Error
}

The execution is completed smoothly at this time, and the SQL statement also contains all fields.

3. Do you feel strange why the scope is FORCE, while I define force in the model?

This has to talk about model_struct.go in another file, gorm package.

func parseTagSetting(tags ) map[string]string {
    setting := map[string]string{}
    for _, str := range []string{("sql"), ("gorm")} {
        if str == "" {
            continue
        }
        tags := (str, ";")
        for _, value := range tags {
            v := (value, ":")
            k := ((v[0]))
            if len(v) >= 2 {
                setting[k] = (v[1:], ":")
            } else {
                setting[k] = k
            }
        }
    }
    return setting
}

This method means parsing all tags defined in orm and converting them to capitalization.

This is the article about the inability to update the field to null value in Golang. For more related content to update the field to null value, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!