如果您不想使用自定义算法重新发明轮子(然后维护它),您可以使用github.com/r3labs/diff/v2。
差异返回一个更改日志,您可以检查它以准确找到更改的内容,格式为 create/update/delete 条目。更改日志也可以编组为 JSON:
package main
import (
"encoding/json"
"github.com/r3labs/diff/v2"
"os"
)
func main() {
x := []int{10, 12, 12, 12, 13}
y := []int{12, 14, 15}
ch, _ := diff.Diff(x, y)
json.NewEncoder(os.Stdout).Encode(ch)
}
它打印更新日志:
[{"type":"delete","path":["0"],"from":10,"to":null},{"type":"update","path":["2"],"from":12,"to":15},{"type":"delete","path":["3"],"from":12,"to":null},{"type":"delete","path":["4"],"from":13,"to":null},{"type":"create","path":["1"],"from":null,"to":14}]
变更日志主要描述了从第一个切片获取第二个切片所需的操作。
该库还提供类似补丁的功能。您可以将更改日志直接传递到 diff.Patch 并将更改应用于目标值:
diff.Patch(ch, &x)
fmt.Println(x) // [12 14 15] just like the 'y' slice
请注意,此差异的默认行为是忽略切片元素顺序。因此,如果您区分 []int{12, 14, 15} 和 []int{12, 15, 14},它将产生一个空的变更日志。
要考虑商品订购,请使用选项diff.SliceOrdering(true):
func main() {
x := []int{12, 15, 14}
y := []int{12, 14, 15}
ch, _ := diff.Diff(x, y, diff.SliceOrdering(true))
json.NewEncoder(os.Stdout).Encode(ch)
// [{"type":"update","path":["1"],"from":15,"to":14},{"type":"update","path":["2"],"from":14,"to":15}]
}