|
1 | 1 | # GO Struct Compare |
2 | | -This repository contains utilities to compare two Go structs and apply the differences to a target struct. |
| 2 | +A Go package for comparing struct instances and applying detected changes. |
3 | 3 |
|
4 | 4 |
|
5 | | -## Example |
6 | | -The following example demonstrates how to compare two structs and apply the changes to the original struct. |
| 5 | +### Installation |
| 6 | +```bash |
| 7 | +go get github.com/rschoonheim/go-struct-compare |
| 8 | +```` |
| 9 | + |
| 10 | +## Overview |
| 11 | +This package provides utilities to: |
| 12 | +- Compare two structs and detect differences (added, modified, or deleted fields) |
| 13 | +- Apply a set of changes to a struct |
| 14 | +- Filter, merge, and manipulate change sets |
| 15 | +- Convert changes to human-readable format or JSON |
| 16 | + |
| 17 | +## Usage |
| 18 | + |
| 19 | +### Basic Comparison |
7 | 20 |
|
8 | 21 | ```go |
9 | 22 | package main |
10 | 23 |
|
11 | | -import "fmt" |
| 24 | +import ( |
| 25 | + "fmt" |
| 26 | + "github.com/rschoonheim/go-struct-compare" |
| 27 | +) |
12 | 28 |
|
13 | 29 | func main() { |
14 | | - // Example usage |
15 | | - type Person struct { |
16 | | - Name string |
17 | | - Age int |
18 | | - Address string |
19 | | - Active bool |
20 | | - } |
21 | | - |
22 | | - old := Person{ |
23 | | - Name: "John Doe", |
24 | | - Age: 30, |
25 | | - Address: "123 Main St", |
26 | | - Active: true, |
27 | | - } |
28 | | - |
29 | | - new := Person{ |
30 | | - Name: "John Doe", |
31 | | - Age: 31, |
32 | | - Address: "456 Oak Ave", |
33 | | - Active: false, |
34 | | - } |
35 | | - |
36 | | - changes, err := CompareStructs(old, new) |
37 | | - if err != nil { |
38 | | - fmt.Printf("Error: %v\n", err) |
39 | | - return |
40 | | - } |
41 | | - |
42 | | - // Apply changes to the original struct |
43 | | - result, err := ApplyChanges(old, changes) |
44 | | - if err != nil { |
45 | | - fmt.Printf("Error applying changes: %v\n", err) |
46 | | - return |
47 | | - } |
48 | | - |
49 | | - // Cast to the correct type |
50 | | - modifiedPerson := result.(Person) |
51 | | - fmt.Printf("Modified person: %+v\n", modifiedPerson) |
| 30 | + type Person struct { |
| 31 | + Name string |
| 32 | + Age int |
| 33 | + Address string |
| 34 | + Active bool |
| 35 | + } |
| 36 | +
|
| 37 | + // Original struct |
| 38 | + old := Person{ |
| 39 | + Name: "John Doe", |
| 40 | + Age: 30, |
| 41 | + Address: "123 Main St", |
| 42 | + Active: true, |
| 43 | + } |
| 44 | +
|
| 45 | + // Modified struct |
| 46 | + new := Person{ |
| 47 | + Name: "John Doe", |
| 48 | + Age: 31, |
| 49 | + Address: "456 Oak Ave", |
| 50 | + Active: false, |
| 51 | + } |
| 52 | +
|
| 53 | + // Compare the structs |
| 54 | + changes, err := comparing_structs_for_changes.CompareStructs(old, new) |
| 55 | + if err != nil { |
| 56 | + fmt.Printf("Error: %v\n", err) |
| 57 | + return |
| 58 | + } |
| 59 | +
|
| 60 | + // Print the changes |
| 61 | + fmt.Println(comparing_structs_for_changes.FormatChanges(changes)) |
| 62 | +} |
| 63 | +``` |
| 64 | +
|
| 65 | +### Applying Changes |
| 66 | +
|
| 67 | +```go |
| 68 | +// Apply changes to the original struct |
| 69 | +result, err := comparing_structs_for_changes.ApplyChanges(old, changes) |
| 70 | +if err != nil { |
| 71 | + fmt.Printf("Error applying changes: %v\n", err) |
| 72 | + return |
| 73 | +} |
| 74 | +
|
| 75 | +// Cast to the correct type |
| 76 | +modifiedPerson := result.(Person) |
| 77 | +fmt.Printf("Modified person: %+v\n", modifiedPerson) |
| 78 | +``` |
| 79 | +
|
| 80 | +### Filtering Changes |
| 81 | +
|
| 82 | +```go |
| 83 | +// Get only modified fields |
| 84 | +modifiedChanges := comparing_structs_for_changes.FilterChanges( |
| 85 | + changes, |
| 86 | + []comparing_structs_for_changes.ChangeType{comparing_structs_for_changes.Modified}, |
| 87 | + nil, |
| 88 | +) |
| 89 | +
|
| 90 | +// Get only changes to specific fields |
| 91 | +addressChanges := comparing_structs_for_changes.FilterChanges( |
| 92 | + changes, |
| 93 | + nil, |
| 94 | + []string{"Address"}, |
| 95 | +) |
| 96 | +``` |
| 97 | +
|
| 98 | +### Working with Change Maps |
| 99 | +
|
| 100 | +```go |
| 101 | +// Convert changes to map for efficient lookup |
| 102 | +changeMap := comparing_structs_for_changes.ChangesToMap(changes) |
| 103 | +
|
| 104 | +// Get change for specific field |
| 105 | +addressChange, exists := changeMap["Address"] |
| 106 | +if exists { |
| 107 | + fmt.Printf("Address changed from %v to %v\n", addressChange.OldValue, addressChange.NewValue) |
| 108 | +} |
| 109 | +``` |
| 110 | +
|
| 111 | +## API Reference |
| 112 | +
|
| 113 | +### Types |
| 114 | +
|
| 115 | +```go |
| 116 | +type ChangeType int |
| 117 | +
|
| 118 | +const ( |
| 119 | + Modified ChangeType = iota |
| 120 | + Added |
| 121 | + Deleted |
| 122 | +) |
| 123 | +
|
| 124 | +type Change struct { |
| 125 | + Field string |
| 126 | + ChangeType ChangeType |
| 127 | + OldValue interface{} |
| 128 | + NewValue interface{} |
52 | 129 | } |
| 130 | +``` |
| 131 | +
|
| 132 | +### Functions |
| 133 | +
|
| 134 | +```go |
| 135 | +// Compares two structs and returns a list of changes |
| 136 | +func CompareStructs(old, new interface{}) ([]Change, error) |
| 137 | +
|
| 138 | +// Applies a list of changes to a struct |
| 139 | +func ApplyChanges(original interface{}, changes []Change) (interface{}, error) |
| 140 | +
|
| 141 | +// Filters changes by type and/or field name |
| 142 | +func FilterChanges(changes []Change, changeTypes []ChangeType, fields []string) []Change |
| 143 | +
|
| 144 | +// Converts a list of changes to a map keyed by field name |
| 145 | +func ChangesToMap(changes []Change) map[string]Change |
| 146 | +
|
| 147 | +// Merges multiple change lists, with later changes taking precedence |
| 148 | +func MergeChanges(changeLists ...[]Change) []Change |
| 149 | +
|
| 150 | +// Returns a human-readable representation of changes |
| 151 | +func FormatChanges(changes []Change) string |
| 152 | +
|
| 153 | +// Serializes changes to JSON |
| 154 | +func ChangesToJSON(changes []Change) ([]byte, error) |
| 155 | +
|
| 156 | +// Deserializes changes from JSON |
| 157 | +func ChangesFromJSON(data []byte) ([]Change, error) |
| 158 | +
|
| 159 | +// Creates a new change list that would undo the given changes |
| 160 | +func RevertChanges(changes []Change) []Change |
| 161 | +``` |
| 162 | +
|
| 163 | +## License |
| 164 | +MIT License |
53 | 165 |
|
54 | | -``` |
| 166 | +## Contributing |
| 167 | +Contributions are welcome! Please feel free to submit a Pull Request. |
0 commit comments