欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang中g(shù)orm無(wú)法將字段更新為空值

 更新時(shí)間:2023年05月25日 16:01:07   作者:空心樹(shù)無(wú)芽  
本文主要介紹了Golang中g(shù)orm無(wú)法將字段更新為空值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

在使用gorm將一個(gè)字段更新為空的時(shí)候,發(fā)現(xiàn)并不生效,不了解具體什么原因,所以此時(shí)需要打開(kāi)debug模式,查看原生SQL是如何執(zhí)行的。

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

查看日志便知,此時(shí)如果name為空字符串,那么update的sql語(yǔ)句中并不會(huì)set,后查閱,方知gorm對(duì)于空字符和0這種數(shù)據(jù),認(rèn)為是不需要處理的,所以。。。

遇到這個(gè)問(wèn)題,有兩種解決方案:

A.更新傳值的時(shí)候通過(guò)map來(lái)指定;

B.修改gorm的源碼包,讓它支持自定義是否可以設(shè)置為空值;

上述兩種方案,第一種比較簡(jiǎn)單,不過(guò)感覺(jué)比較low,所以我選擇嘗試第二種。

當(dāng)然第二種,也有它的問(wèn)題,比如被更新之后,得手動(dòng)去調(diào)整回來(lái)。

下面重點(diǎn)講解第二種方案的實(shí)施。

1、找到gorm包下的scope.go文件

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 := reflect.ValueOf(values)
        switch reflectValue.Kind() {
        case reflect.Map:
            for _, key := range reflectValue.MapKeys() {
                attrs[ToColumnName(key.Interface().(string))] = reflectValue.MapIndex(key).Interface()
            }
        default:
            for _, field := range (&Scope{Value: values, db: db}).Fields() {
                if !field.IsBlank && (withIgnoredField || !field.IsIgnored) {
                    attrs[field.DBName] = field.Field.Interface()
                }
            }
        }
    }
    return attrs
}

上面代碼表示我們傳遞過(guò)來(lái)的數(shù)據(jù)會(huì)被轉(zhuǎn)為map型,然后再進(jìn)行數(shù)據(jù)庫(kù)字段更新,這個(gè)代碼很簡(jiǎn)單,就是把滿足條件保存到map。

我們要解決的是空值能夠更新,則和field.IsBlank相關(guān)聯(lián),接著找到下一個(gè)方法;

// Fields get value's 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)
                }
                //判斷model中字段有沒(méi)有force字段,此處使用Force,是因?yàn)榻馕鰐ag時(shí),統(tǒng)一轉(zhuǎn)成了大寫
                _, ok := structField.TagSettingsGet("FORCE")
                //如果字段為空值,且字段存在則設(shè)定為false
                fields = append(fields, &Field{StructField: structField, Field: fieldValue, IsBlank: isBlank(fieldValue) && !ok})
            } else {
                fields = append(fields, &Field{StructField: structField, IsBlank: true})
            }
        }
        scope.fields = &fields
    }
    return *scope.fields
}

注意上面帶注釋的兩行,作用就不再贅述了。

2、修改我們的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 = db.Model(&Content{}).Debug().Where("id = ?", 123).Update(&content).Error
}

此時(shí)執(zhí)行則順利完成,SQL語(yǔ)句也包含了所有字段。

3、你有沒(méi)有感到奇怪,為什么scope里面校驗(yàn)的是FORCE,而我在model中則定義的是force?

這就要說(shuō)到另一個(gè)文件 gorm包下的 model_struct.go

func parseTagSetting(tags reflect.StructTag) map[string]string {
    setting := map[string]string{}
    for _, str := range []string{tags.Get("sql"), tags.Get("gorm")} {
        if str == "" {
            continue
        }
        tags := strings.Split(str, ";")
        for _, value := range tags {
            v := strings.Split(value, ":")
            k := strings.TrimSpace(strings.ToUpper(v[0]))
            if len(v) >= 2 {
                setting[k] = strings.Join(v[1:], ":")
            } else {
                setting[k] = k
            }
        }
    }
    return setting
}

這個(gè)方法表示將orm中定義的tag標(biāo)簽,全部解析并轉(zhuǎn)化為大寫。

到此這篇關(guān)于Golang中g(shù)orm無(wú)法將字段更新為空值的文章就介紹到這了,更多相關(guān)gorm 字段更新為空值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go?復(fù)合類型之字典類型使用教程示例

    Go?復(fù)合類型之字典類型使用教程示例

    這篇文章主要為大家介紹了Go復(fù)合類型之字典類型使用教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • Go語(yǔ)言中使用 buffered channel 實(shí)現(xiàn)線程安全的 pool

    Go語(yǔ)言中使用 buffered channel 實(shí)現(xiàn)線程安全的 pool

    這篇文章主要介紹了Go語(yǔ)言中使用 buffered channel 實(shí)現(xiàn)線程安全的 pool,因?yàn)镚o語(yǔ)言自帶的sync.Pool并不是很好用,所以自己實(shí)現(xiàn)了一線程安全的 pool,需要的朋友可以參考下
    2014-10-10
  • Go1.18新特性使用Generics泛型進(jìn)行流式處理

    Go1.18新特性使用Generics泛型進(jìn)行流式處理

    這篇文章主要為大家介紹了Go1.18新特性使用Generics泛型進(jìn)行流式處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go并發(fā)的方法之goroutine模型與調(diào)度策略

    Go并發(fā)的方法之goroutine模型與調(diào)度策略

    在go中,協(xié)程co-routine被改為goroutine,一個(gè)goroutine只占幾kb,因此可以有大量的goroutine存在,另一方面goroutine 的調(diào)度器非常靈活,本文給大家介紹下Go并發(fā)的方法之goroutine模型與調(diào)度策略,感興趣的朋友一起看看吧
    2021-11-11
  • 探究gRPC?客戶端調(diào)用服務(wù)端需要連接池嗎?

    探究gRPC?客戶端調(diào)用服務(wù)端需要連接池嗎?

    這篇文章主要為大家介紹了gRPC?客戶端調(diào)用服務(wù)端需要連接池嗎的問(wèn)題探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Ubuntu18.04 LTS搭建GO語(yǔ)言開(kāi)發(fā)環(huán)境過(guò)程解析

    Ubuntu18.04 LTS搭建GO語(yǔ)言開(kāi)發(fā)環(huán)境過(guò)程解析

    這篇文章主要介紹了Ubuntu18.04 LTS搭建GO語(yǔ)言開(kāi)發(fā)環(huán)境過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 深入理解Golang?make和new的區(qū)別及實(shí)現(xiàn)原理

    深入理解Golang?make和new的區(qū)別及實(shí)現(xiàn)原理

    在Go語(yǔ)言中,有兩個(gè)比較雷同的內(nèi)置函數(shù),分別是new和make方法,二者都可以用來(lái)分配內(nèi)存,那他們有什么區(qū)別呢?下面我們就從底層來(lái)分析一下二者的不同。感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助
    2022-10-10
  • Go語(yǔ)言編程通過(guò)dwarf獲取內(nèi)聯(lián)函數(shù)

    Go語(yǔ)言編程通過(guò)dwarf獲取內(nèi)聯(lián)函數(shù)

    這篇文章主要為大家介紹了Go語(yǔ)言編程通過(guò)dwarf獲取內(nèi)聯(lián)函數(shù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • go簡(jiǎn)介及國(guó)內(nèi)鏡像源配置全過(guò)程

    go簡(jiǎn)介及國(guó)內(nèi)鏡像源配置全過(guò)程

    本文介紹了Go語(yǔ)言的基本概念和環(huán)境配置,包括GOROOT、GOPATH和GOMODULE的設(shè)置,還展示了如何在IDEA中配置Go語(yǔ)言的開(kāi)發(fā)環(huán)境,并通過(guò)一個(gè)簡(jiǎn)單的“HelloWorld”項(xiàng)目來(lái)熟悉Go語(yǔ)言的基本語(yǔ)法和開(kāi)發(fā)流程
    2025-01-01
  • go如何終止多個(gè)for select循環(huán)嵌套的方法

    go如何終止多個(gè)for select循環(huán)嵌套的方法

    當(dāng)您想從嵌套循環(huán)中中斷,從select內(nèi)部終止循環(huán)時(shí),標(biāo)記的中斷非常有用,本文主要介紹了go如何終止多個(gè)for select循環(huán)嵌套的方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01

最新評(píng)論