Quickstart
From an empty module to an applied patch in five minutes.
Install
go get github.com/deltamesh/deltamesh@v1.9.2
The module has no third-party dependencies. Go 1.21 or newer is required for the iterator interfaces.
Compute a patch
package main import ( "context" "os" "github.com/deltamesh/deltamesh" ) func main() { old, _ := os.Open("snapshot-a.json") new, _ := os.Open("snapshot-b.json") defer old.Close() defer new.Close() d := deltamesh.NewDiffer(deltamesh.JSON()) patch, err := d.Diff(context.Background(), old, new) if err != nil { panic(err) } patch.WriteTo(os.Stdout) }
Apply it
a := deltamesh.NewApplier(deltamesh.JSON()) if err := a.Apply(ctx, src, patch, dst); err != nil { log.Fatalf("apply: %v", err) }
Note.
Apply streams into dst as it reads src. Do not point both at the same file — use a temporary file and rename on success.Configuration
Options are passed to NewDiffer and are all optional.
| Option | Default | Effect |
|---|---|---|
WithMaxDepth(n) | 256 | Aborts with ErrTooDeep beyond n levels |
WithKeyOrder(f) | lexical | Comparison order for map keys |
WithMoveDetection(b) | true | Emits Move instead of Delete+Insert pairs |
WithCompactDeletes(b) | false | Smaller patches, but no longer reversible |
WithBufferSize(n) | 64 KiB | Read buffer per side |
Benchmarks
Measured on a 2023 Ryzen 7 7840U, Go 1.22, single core, inputs on tmpfs.
| Input pair | Time | Peak RSS | Patch size |
|---|---|---|---|
| 12 MB catalogue, 0.4% changed | 81 ms | 9 MB | 54 KB |
| 410 MB export, 2% changed | 2.6 s | 14 MB | 9.1 MB |
| 4.1 GB array, 0.1% changed | 27 s | 19 MB | 4.4 MB |