merger

package module
v0.0.0-...-acc2824 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 17, 2017 License: MIT Imports: 2 Imported by: 0

README

Merger

This Go package merges different types together. Nested types will be merged too. This can be useful for:

  • Merging configurations from different sources
  • Deduplicate items before serialization
  • Setting field preferences

It works with Go 1.7 and greater

Usage

Documentation with examples is available on https://godoc.org/github.com/djboris9/merger This readme is only an introduction.

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)

Example

Full usage example:

package main

import (
	"encoding/json"
	"fmt"
	"log"

	"github.com/djboris9/merger"
)

func main() {
	A := struct {
		FieldA string
		FieldB string
		FieldC []int
	}{
		"aAaA",
		"bBbB",
		[]int{1, 2},
	}

	B := struct {
		FieldA string
		FieldC []int
	}{
		"NewVal",
		[]int{3, 4},
	}

	// Merge struct A and B together
	V, err := merger.Merge(A, B)
	if err != nil {
		log.Fatal(err)
	}

	// Print it
	ser, _ := json.Marshal(V)
	fmt.Println(string(ser))
	// Output: {"FieldA":"NewVal","FieldB":"bBbB","FieldC":[1,2,3,4]}
}

Merging maps:

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 slices:

A := []int{1, 2, 3}
B := []int{4, 5, 6}
V, _ := merger.Merge(A, B)
// V: []int{1, 2, 3, 4, 5}

Other examples are in the godoc.

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

View Source
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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL