diff
diff copied to clipboard
net.IP comparable as String.
How do I force differ function so it would compare net.IP as a string and not as a slice?
https://go.dev/play/p/0VMlM5RQ9WO
package main
import (
"log"
"net"
"github.com/davecgh/go-spew/spew"
"github.com/r3labs/diff/v2"
)
type LoadBalancer struct {
IP []net.IP
}
func main() {
x := LoadBalancer{
IP: []net.IP{
net.ParseIP("192.0.2.1"),
net.ParseIP("192.0.2.2"),
},
}
y := LoadBalancer{
IP: []net.IP{
net.ParseIP("192.0.2.1"),
net.ParseIP("192.0.2.3"),
},
}
changelog, err := diff.Diff(x, y)
if err != nil {
log.Fatal(err)
}
spew.Dump(changelog)
}
(diff.Changelog) (len=1 cap=1) {
(diff.Change) {
Type: (string) (len=6) "update",
Path: ([]string) (len=3 cap=3) {
(string) (len=2) "IP",
(string) (len=1) "1",
(string) (len=2) "15"
},
From: (uint8) 2,
To: (uint8) 3,
parent: (interface {}) <nil>
}
}
To accomplish this, I implemented a custom ValueDiffer which looks like the following:
Instantiation
type NetIPDiffer struct {
DiffFunc (func(path []string, a, b reflect.Value, p interface{}) error)
}
func (differ NetIPDiffer) Match(a, b reflect.Value) bool {
return diff.AreType(a, b, reflect.TypeOf(net.IP{}))
}
func (differ NetIPDiffer) Diff(dt diff.DiffType, df diff.DiffFunc, cl *diff.Changelog, path []string, a, b reflect.Value, p interface{}) 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
}
aString := a.Interface().(net.IP).String()
bString := b.Interface().(net.IP).String()
if aString != bString {
cl.Add(diff.UPDATE, path, aString, bString)
}
return nil
}
func (differ NetIPDiffer) InsertParentDiffer(dfunc func(path []string, a, b reflect.Value, p interface{}) error) {
differ.DiffFunc = dfunc
}
Use
d, err := diff.NewDiffer(
diff.DisableStructValues(),
diff.SliceOrdering(true),
diff.CustomValueDiffers(&NetIPDiffer{}),
)
For reference, I looked at the internal diff_test.go file to put this stuff together.
@tyliec nice, I think this should be in docs at least