亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何使用 r3labs/diff 區分整個結構

如何使用 r3labs/diff 區分整個結構

Go
ABOUTYOU 2022-10-17 10:05:57
我遇到了github.com/r3labs/diffGo 語言庫來比較相同類型的兩個結構。庫運行良好,除了一個用例如下:我使用Date結構來表示日期:type Date struct {    Year  int    Month int    Day   int}現在,還有一些其他更復雜的結構可以使用該Date結構,例如:type Student struct {  DateOfBirth Date}如果我要比較兩個學生,比如diff.Diff(  Student{DateOfBirth: Date{2021, 11, 13}},  Student{DateOfBirth: Date{2021, 10, 9}},)結果我會得到一個包含 2 個項目的更改日志,一個DateOfBirth > Month用于DateOfBirth > Day.我想要的結果將是一個帶有單個項目 ( DateOfBirth) 和2021-10-09.圖書館有可能嗎?
查看完整描述

2 回答

?
翻閱古今

TA貢獻1780條經驗 獲得超5個贊

注意此解決方案正在使用github.com/r3labs/diff/v2.

沒有這樣的選擇。diff 只是遞歸地處理結構字段并為每個不同的字段生成更改日志。

要實現您想要的輸出,您可以實現自己的ValueDiffer. 這樣,您可以“原子地”區分結構并以您想要的格式附加到變更日志。

一個人為的例子,部分從包內部復制:

type DateDiffer struct {

}


// Whether this differ should be used to match a specific type

func (d *DateDiffer) Match(a, b reflect.Value) bool {

    return diff.AreType(a, b, reflect.TypeOf(Date{}))

}


// The actual diff function, where you also append to the changelog

// using your custom format

func (d *DateDiffer) Diff(cl *diff.Changelog, path []string, a, b reflect.Value) error {

    if a.Kind() == reflect.Invalid {

        cl.Add(diff.CREATE, path, nil, b.Interface())

        return nil

    }

    if b.Kind() == reflect.Invalid {

        cl.Add(diff.DELETE, path, a.Interface(), nil)

        return nil

    }

    var d1, d2 Date

    d1, _ = a.Interface().(Date)

    d2, _ = b.Interface().(Date)

    if d1.Day != d2.Day || d1.Month != d2.Month || d1.Year != d2.Year {

        cl.Add(diff.UPDATE, path, fmt.Sprintf("%d-%d-%d", d1.Year, d1.Month, d1.Day), fmt.Sprintf("%d-%d-%d", d2.Year, d2.Month, d2.Day))

    }

    return nil

}


// unsure what this is actually for, but you must implement it either way

func (d *DateDiffer) InsertParentDiffer(dfunc func(path []string, a, b reflect.Value, p interface{}) error) {

    return

}

然后你這樣使用它:


    d2, _ := diff.NewDiffer(diff.CustomValueDiffers(&DateDiffer{}))


    s1 := Student{DateOfBirth: Date{2021, 11, 13}}

    s2 := Student{DateOfBirth: Date{2021, 10, 9}}


    ch2, _ := d2.Diff(s1, s2)

輸出(編組和縮進的 json):


[

  {

   "type": "update",

   "path": [

    "DateOfBirth"

   ],

   "from": "2021-11-13",

   "to": "2021-10-9"

  }

 ]


查看完整回答
反對 回復 2022-10-17
?
喵喔喔

TA貢獻1735條經驗 獲得超5個贊

經過一番研究,我找到了解決方案。


我需要為 the 創建一個自定義差異,Date并使用DisableStructValues包中的選項。


此選項很有用,因為它禁止為結構中的每個項目填充單獨的更改,并在將其與nil值進行比較時返回整個對象。


diff.Diff(

  Student{DateOfBirth: Date{2021, 11, 13}},

  Student{DateOfBirth: Date{2021, 10, 9}},

  diff.CustomValueDiffers(differ.DateDiffer{}),

  diff.DisableStructValues()

)

要實現自定義差異,需要一個實現以下接口的新結構:


type ValueDiffer interface {

    Match(a, b reflect.Value) bool

    Diff(cl *Changelog, path []string, a, b reflect.Value) error

    InsertParentDiffer(dfunc func(path []string, a, b reflect.Value, p interface{}) error)

}

這是我的自定義不同的實現。


type DateDiffer struct {

    DiffFunc (func(path []string, a, b reflect.Value, p interface{}) error)

}


func (differ DateDiffer) Match(a, b reflect.Value) bool {

    return diff.AreType(a, b, reflect.TypeOf(Date{}))

}


func (differ DateDiffer) Diff(cl *diff.Changelog, path []string, a, b reflect.Value) error {

    if a.Kind() == reflect.Invalid {

        cl.Add(diff.CREATE, path, nil, b.Interface())

        return nil

    }


    if b.Kind() == reflect.Invalid {

        cl.Add(diff.DELETE, path, a.Interface(), nil)

        return nil

    }


    var source, target Date

    source, _ = a.Interface().(Date)

    target, _ = b.Interface().(Date)

    if !source.Equal(target) {

        cl.Add(diff.UPDATE, path, a.Interface(), b.Interface())

    }


    return nil

}


func (differ DateDiffer) InsertParentDiffer(dfunc func(path []string, a, b reflect.Value, p interface{}) error) {

    differ.DiffFunc = dfunc

}

希望這會幫助有類似用例的人。


查看完整回答
反對 回復 2022-10-17
  • 2 回答
  • 0 關注
  • 165 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號