Documentation
¶
Overview ¶
Package merger can merge different Go types together.
This can be useful for:
- Merging configurations from different sources
- Deduplicate items before serialization
- Setting field preferences
Merge Algorithm ¶
Let A be the first arbitrary value and B be the second arbitrary value with precedence.
boolean, numeric and string types will be overwritten by the argument with precedence (B). slice and array types will be concatenated (A ∥ B). struct and map types will be merged together giving a union of all fields, where the values of them are merged too (A ∪ B)
Merge Examples ¶
Merging boolean, numeric, string types (overwrite):
A := "a" B := 4 V, _ := merger.Merge(A, B) // V: 4
Merging map, struct types (union):
A := map[string]int{
"x": 1,
"y": 2,
}
B := map[string]int{
"a": 1,
"b": 2,
}
V, _ := merger.Merge(A, B)
// V: map[string]int{"a": 1, "b": 2, "x": 1, "y": 2}
Merging slice, array types (concat):
A := []int{1, 2, 3}
B := []int{4, 5, 6}
V, _ := merger.Merge(A, B)
// V: []int{1, 2, 3, 4, 5, 6}
Merging embedded types:
A := map[string]interface{}{
"a": []int{1, 2},
"b": "aAaAaA",
"c": map[int]int{1: 10, 2: 20},
}
B := map[string]interface{}{
"a": []int{3, 4},
"b": "bBbBbB",
"c": map[int]int{1: 100, 3: 30},
}
V, _ := merger.Merge(A, B)
// V: map[string]interface{}{"a": []int{1,2,3,4}, "b": "bBbBbB", "c": map[int]int{1:100, 2:20, 3:30}}
Index ¶
Examples ¶
Constants ¶
const ( ErrDiffKind = 1 << iota ErrMergeUnsupported = 1 << iota ErrInvalidFields = 1 << iota ErrDiffArrayTypes = 1 << iota ErrDiffSliceTypes = 1 << iota ErrDiffMapKeyTypes = 1 << iota ErrDiffMapValueTypes = 1 << iota )
MergeError types with value 2ⁿ
Variables ¶
This section is empty.
Functions ¶
func Merge ¶
func Merge(a interface{}, b interface{}) (interface{}, error)
Merge merges a and b together where b has precedence. It is not destructive on their parameters, but these must not be modified while merge is in progress.
Example ¶
// Create struct A
A := struct {
FieldA string
FieldB string
FieldC []int
}{
"aAaA",
"bBbB",
[]int{1, 2},
}
// Create struct B
B := struct {
FieldA string
FieldC []int
}{
"NewVal",
[]int{3, 4},
}
// Merge struct A and B together
V, err := Merge(A, B)
if err != nil {
log.Fatal(err)
}
// Serialize
ser, _ := json.Marshal(V)
fmt.Println(string(ser))
Output: {"FieldA":"NewVal","FieldB":"bBbB","FieldC":[1,2,3,4]}
Example (Nested) ¶
// Create two maps with nested types
A := map[string]interface{}{
"a": []int{1, 2},
"b": "aAaAaA",
"c": map[int]int{1: 10, 2: 20},
}
B := map[string]interface{}{
"a": []int{3, 4},
"b": "bBbBbB",
"c": map[int]int{1: 100, 3: 30},
"d": "Only in B",
}
// Merge map A and B together, including their values
V, err := Merge(A, B)
if err != nil {
log.Fatal(err)
}
// Serialize
ser, _ := json.Marshal(V)
fmt.Println(string(ser))
Output: {"a":[1,2,3,4],"b":"bBbBbB","c":{"1":100,"2":20,"3":30},"d":"Only in B"}
Types ¶
type MergeError ¶
type MergeError struct {
// contains filtered or unexported fields
}
MergeError represents an error which has occurred while merging
func (*MergeError) Error ¶
func (e *MergeError) Error() string
func (*MergeError) Type ¶
func (e *MergeError) Type() int
Type returns the MergeError type which is one or multiple of Err constants by 2ⁿ
Notes ¶
Bugs ¶
When merging structs fields are appended (A.Fields ∥ B.Fields). But field types should be taken from b as it has precedence.