Documentation
¶
Overview ¶
Package deep provides high-performance, type-safe deep diff, copy, equality, and patch-apply operations for Go values.
Architecture ¶
Deep operates on Patch values — flat, serializable lists of Operation records describing changes between two values of the same type. The four core operations are:
- Diff computes the patch from a to b.
- Apply applies a patch to a target pointer.
- Equal reports whether two values are deeply equal.
- Clone returns a deep copy of a value.
Code Generation ¶
For production use, run deep-gen to generate reflection-free implementations of all four operations for your types:
//go:generate go run github.com/brunoga/deep/v5/cmd/deep-gen -type=MyType .
Generated code is 4–14x faster than the reflection fallback and is used automatically — no API changes required. The reflection engine remains as a transparent fallback for types without generated code.
Patch Construction ¶
Patches can be computed via Diff or built manually with Edit. Typed operation constructors (Set, Add, Remove, Move, Copy) return an Op value that can be passed to Builder.With for a fluent, type-safe chain:
patch := deep.Edit(&user).
With(
deep.Set(nameField, "Alice"),
deep.Set(ageField, 30).If(deep.Gt(ageField, 0)),
).
Guard(deep.Gt(ageField, 18)).
Build()
Field creates type-safe path selectors from struct field accessors. At and MapKey extend paths into slices and maps with full type safety.
Conditions ¶
Per-operation guards are attached to Op values via Op.If and Op.Unless. A global patch guard is set via Builder.Guard or Patch.WithGuard. Conditions are serializable and survive JSON round-trips.
Causality and CRDTs ¶
The [crdt] sub-package provides [crdt.LWW], a generic Last-Write-Wins register; [crdt.CRDT], a concurrency-safe wrapper for any type; and [crdt.Text], a convergent collaborative text type.
Serialization ¶
Patch marshals to/from JSON natively. Patch.ToJSONPatch and ParseJSONPatch interoperate with RFC 6902 JSON Patch (with deep extensions for conditions and log operations).
Index ¶
- Constants
- func And(conds ...*condition.Condition) *condition.Condition
- func Apply[T any](target *T, p Patch[T], opts ...ApplyOption) error
- func Clone[T any](v T) T
- func Eq[T, V any](p Path[T, V], val V) *condition.Condition
- func Equal[T any](a, b T) bool
- func Exists[T, V any](p Path[T, V]) *condition.Condition
- func Ge[T, V any](p Path[T, V], val V) *condition.Condition
- func Gt[T, V any](p Path[T, V], val V) *condition.Condition
- func In[T, V any](p Path[T, V], vals []V) *condition.Condition
- func Le[T, V any](p Path[T, V], val V) *condition.Condition
- func Lt[T, V any](p Path[T, V], val V) *condition.Condition
- func Matches[T, V any](p Path[T, V], regex string) *condition.Condition
- func Ne[T, V any](p Path[T, V], val V) *condition.Condition
- func Not(c *condition.Condition) *condition.Condition
- func Or(conds ...*condition.Condition) *condition.Condition
- func Type[T, V any](p Path[T, V], typeName string) *condition.Condition
- type ApplyError
- type ApplyOption
- type Builder
- type ConflictResolver
- type Op
- type OpKind
- type Operation
- type Patch
- type Path
Constants ¶
Variables ¶
This section is empty.
Functions ¶
func Apply ¶
func Apply[T any](target *T, p Patch[T], opts ...ApplyOption) error
Apply applies a Patch to a target pointer. v5 prioritizes the generated Patch method but falls back to reflection if needed.
Note: when a Patch has been serialized to JSON and decoded, numeric values in Operation.Old and Operation.New will be float64 regardless of the original type. This affects strict-mode Old-value checks.
Types ¶
type ApplyError ¶
type ApplyError struct {
Errors []error
}
ApplyError represents one or more errors that occurred during patch application.
func (*ApplyError) Error ¶
func (e *ApplyError) Error() string
func (*ApplyError) Unwrap ¶
func (e *ApplyError) Unwrap() []error
Unwrap implements the errors.Join interface, allowing errors.Is and errors.As to inspect individual errors within the ApplyError.
type ApplyOption ¶
type ApplyOption func(*applyConfig)
ApplyOption configures the behaviour of Apply.
func WithLogger ¶
func WithLogger(l *slog.Logger) ApplyOption
WithLogger sets the slog.Logger used for OpLog operations within a single Apply call. If not provided, slog.Default is used.
type Builder ¶
type Builder[T any] struct { // contains filtered or unexported fields }
Builder constructs a Patch via a fluent chain.
func Edit ¶
Edit returns a Builder for constructing a Patch[T]. The target argument is used only for type inference and is not stored; the builder produces a standalone Patch, not a live view of the target.
func (*Builder[T]) Guard ¶
Guard sets the global guard condition on the patch. If Guard has already been called, the new condition is ANDed with the existing one rather than replacing it — calling Guard twice is equivalent to Guard(And(c1, c2)).
type ConflictResolver ¶
ConflictResolver defines how to resolve merge conflicts.
type Op ¶
type Op struct {
// contains filtered or unexported fields
}
Op is a pending patch operation. Obtain one from Set, Add, Remove, Move, or Copy; attach per-operation conditions with Op.If or Op.Unless before passing to Builder.With.
func Copy ¶
Copy returns a type-safe copy operation that duplicates the value at from to to. Both paths must share the same value type V.
func Move ¶
Move returns a type-safe move operation that relocates the value at from to to. Both paths must share the same value type V.
type Operation ¶
Operation is an alias for the internal engine operation type.
Note: after JSON round-trip, numeric Old/New values become float64.
type Patch ¶
type Patch[T any] struct { // Guard is a global Condition that must be satisfied before any operation // in this patch is applied. Set via WithGuard or Builder.Guard. Guard *condition.Condition `json:"cond,omitempty"` // Operations is a flat list of changes. Operations []Operation `json:"ops"` // Strict mode enables Old value verification. Strict bool `json:"strict,omitempty"` // contains filtered or unexported fields }
Patch is a pure data structure representing a set of changes to type T. It is designed to be easily serializable and manipulatable.
func Diff ¶
Diff compares two values and returns a Patch describing the changes from a to b. Generated types (produced by deep-gen) dispatch to a reflection-free implementation. For other types, Diff falls back to the reflection engine which may return an error for unsupported kinds (chan, func, etc.).
func Merge ¶
func Merge[T any](base, other Patch[T], r ConflictResolver) Patch[T]
Merge combines two patches into a single patch, resolving conflicts. Operations are deduplicated by path. When both patches modify the same path, r.Resolve is called if r is non-nil; otherwise other's operation wins over base. The output operations are sorted by path for deterministic ordering.
func ParseJSONPatch ¶
ParseJSONPatch parses a JSON Patch document (RFC 6902 plus deep extensions) back into a Patch[T]. This is the inverse of Patch.ToJSONPatch().
func (Patch[T]) AsStrict ¶
AsStrict returns a new patch with strict mode enabled. When strict mode is on, every Replace and Remove operation verifies the current value matches Op.Old before applying; mismatches return an error.
func (Patch[T]) ToJSONPatch ¶
ToJSONPatch returns a JSON Patch representation compatible with RFC 6902 and the github.com/brunoga/jsonpatch extensions.
type Path ¶
type Path[T, V any] struct { // contains filtered or unexported fields }
Path represents a type-safe path to a field of type V within type T.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
deep-gen
command
|
|
|
Package crdt provides Conflict-free Replicated Data Types (CRDTs) built on top of the deep patch engine.
|
Package crdt provides Conflict-free Replicated Data Types (CRDTs) built on top of the deep patch engine. |
|
hlc
Package hlc implements a Hybrid Logical Clock (HLC) for distributed causality tracking.
|
Package hlc implements a Hybrid Logical Clock (HLC) for distributed causality tracking. |
|
examples
|
|
|
atomic_config
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
audit_logging
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
concurrent_updates
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
config_manager
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
crdt_sync
command
|
|
|
http_patch_api
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
json_interop
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
keyed_inventory
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
lww_fields
command
|
|
|
move_detection
command
|
|
|
multi_error
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
policy_engine
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
state_management
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
struct_map_keys
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
text_sync
command
|
|
|
three_way_merge
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
websocket_sync
command
Code generated by deep-gen.
|
Code generated by deep-gen. |
|
internal
|
|
|
testmodels
Code generated by deep-gen.
|
Code generated by deep-gen. |