Copyright 2013 Dario Castañé. All rights reserved. Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Based on src/pkg/reflect/deepequal.go from official golang's stdlib.

package mergo

import (
	
	
	
)

func ( reflect.Value) ( bool) {
	for ,  := 0, .NumField();  < ; ++ {
		 := .Type().Field()
		if isExportedComponent(&) {
			return true
		}
	}
	return
}

func ( *reflect.StructField) bool {
	 := .Name
	 := .PkgPath
	if len() > 0 {
		return false
	}
	 := [0]
	if 'a' <=  &&  <= 'z' ||  == '_' {
		return false
	}
	return true
}

type Config struct {
	Overwrite                    bool
	AppendSlice                  bool
	TypeCheck                    bool
	Transformers                 Transformers
	overwriteWithEmptyValue      bool
	overwriteSliceWithEmptyValue bool
}

type Transformers interface {
	Transformer(reflect.Type) func(dst, src reflect.Value) error
}
Traverses recursively both values, assigning src's fields values to dst. The map argument tracks comparisons that have already been seen, which allows short circuiting on recursive types.
func (,  reflect.Value,  map[uintptr]*visit,  int,  *Config) ( reflect.Value,  error) {
	 = 
	 := .Overwrite
	 := .TypeCheck
	 := .overwriteWithEmptyValue
	 := .overwriteSliceWithEmptyValue

	if !.IsValid() {
		return
	}

	if .CanAddr() {
		 := .UnsafeAddr()
		 := 17 * 
		 := []
		 := .Type()
		for  := ;  != nil;  = .next {
			if .ptr ==  && .typ ==  {
				return , nil
			}
Remember, remember...
		[] = &visit{, , }
	}

	if .Transformers != nil && !isEmptyValue() {
		if  := .Transformers.Transformer(.Type());  != nil {
			 = (, )
			return
		}
	}

	if .IsValid() && .IsValid() && .Type() != .Type() {
		 = fmt.Errorf("cannot append two different types (%s, %s)", .Kind(), .Kind())
		return
	}

	switch .Kind() {
	case reflect.Struct:
		if hasExportedField() {
			 := reflect.New(.Type()).Elem()
			for ,  := 0, .NumField();  < ; ++ {
				 := .Field()
copy un-exported struct fields
				if !isExportedComponent(&) {
					 := .Field()
					 = reflect.NewAt(.Type(), unsafe.Pointer(.UnsafeAddr())).Elem() //nolint:gosec
					 := .Field()
					if !.Field().CanAddr() {
						continue
					}

					 = reflect.NewAt(.Type(), unsafe.Pointer(.UnsafeAddr())).Elem() //nolint:gosec
					.Set()
					continue
				}
				,  = (, .Field(), , +1, )
				if  != nil {
					return
				}
				.Field().Set()
			}

			if .CanSet() {
				.Set()
			} else {
				 = 
			}
			return
		} else {
			if (isReflectNil() || ) && (!isEmptyValue() || ) {
				 = 
			}
		}

	case reflect.Map:
		if .IsNil() && !.IsNil() {
			if .CanSet() {
				.Set(reflect.MakeMap(.Type()))
			} else {
				 = 
				return
			}
		}
		for ,  := range .MapKeys() {
			 := .MapIndex()
			 := .MapIndex()
			if !.IsValid() {
				continue
			}
			if .MapIndex().IsValid() {
				 := .Interface()
				 = reflect.ValueOf()
			}
			if isReflectNil() {
				if  || isReflectNil() {
					.SetMapIndex(, )
				}
				continue
			}
			if !.CanInterface() {
				continue
			}

			if .CanInterface() {
				 = reflect.ValueOf(.Interface())
				if .IsValid() {
					 = reflect.ValueOf(.Interface())
				}
			}
			,  = (, , , +1, )
			if  != nil {
				return
			}
			.SetMapIndex(, )

		}
	case reflect.Slice:
		 := 
		if (!isEmptyValue() ||  || ) && ( || isEmptyValue()) && !.AppendSlice {
			if  && .Type() != .Type() {
				return , fmt.Errorf("cannot override two slices with different type (%s, %s)", .Type(), .Type())
			}
			 = 
		} else if .AppendSlice {
			if  && .Type() != .Type() {
				 = fmt.Errorf("cannot append two slice with different type (%s, %s)", .Type(), .Type())
				return
			}
			 = reflect.AppendSlice(, )
		}
		if .CanSet() {
			.Set()
		} else {
			 = 
		}
	case reflect.Ptr, reflect.Interface:
		if isReflectNil() {
			break
		}

		if .Kind() != reflect.Ptr && .Type().AssignableTo(.Type()) {
			if .IsNil() ||  {
				if  || isEmptyValue() {
					if .CanSet() {
						.Set()
					} else {
						 = 
					}
				}
			}
			break
		}

		if .Kind() != reflect.Interface {
			if .IsNil() || (.Kind() != reflect.Ptr && ) {
				if .CanSet() && ( || isEmptyValue()) {
					.Set()
				}
			} else if .Kind() == reflect.Ptr {
				if ,  = (.Elem(), .Elem(), , +1, );  != nil {
					return
				}
				 = .Addr()
			} else if .Elem().Type() == .Type() {
				if ,  = (.Elem(), , , +1, );  != nil {
					return
				}
			} else {
				return , ErrDifferentArgumentsTypes
			}
			break
		}
		if .IsNil() ||  {
			if ( || isEmptyValue()) && ( || !isEmptyValue()) {
				if .CanSet() {
					.Set()
				} else {
					 = 
				}
			}
		} else if _,  = (.Elem(), .Elem(), , +1, );  != nil {
			return
		}
	default:
		 := (!isEmptyValue() || ) && ( || isEmptyValue())
		if  {
			if .CanSet() {
				.Set()
			} else {
				 = 
			}
		}
	}

	return
}
Merge will fill any empty for value type attributes on the dst struct using corresponding src attributes if they themselves are not empty. dst and src must be valid same-type structs and dst must be a pointer to struct. It won't merge unexported (private) fields and will do recursively any exported field.
func (,  interface{},  ...func(*Config)) error {
	return merge(, , ...)
}
MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by non-empty src attribute values. Deprecated: use Merge(…) with WithOverride
func (,  interface{},  ...func(*Config)) error {
	return merge(, , append(, WithOverride)...)
}
WithTransformers adds transformers to merge, allowing to customize the merging of some types.
func ( Transformers) func(*Config) {
	return func( *Config) {
		.Transformers = 
	}
}
WithOverride will make merge override non-empty dst attributes with non-empty src attributes values.
func ( *Config) {
	.Overwrite = true
}
WithOverwriteWithEmptyValue will make merge override non empty dst attributes with empty src attributes values.
WithOverrideEmptySlice will make merge override empty dst slice with empty src slice.
WithAppendSlice will make merge append slices instead of overwriting it.
func ( *Config) {
	.AppendSlice = true
}
WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride).
func ( *Config) {
	.TypeCheck = true
}

func (,  interface{},  ...func(*Config)) error {
	var (
		,  reflect.Value
		        error
	)

	 := &Config{}

	for ,  := range  {
		()
	}

	if , ,  = resolveValues(, );  != nil {
		return 
	}
	if !.CanSet() {
		return fmt.Errorf("cannot set dst, needs reference")
	}
	if .Type() != .Type() {
		return ErrDifferentArgumentsTypes
	}
	_,  = deepMerge(, , make(map[uintptr]*visit), 0, )
	return 
}
IsReflectNil is the reflect value provided nil
func ( reflect.Value) bool {
	 := .Kind()
	switch  {
Both interface and slice are nil if first word is 0. Both are always bigger than a word; assume flagIndir.
		return .IsNil()
	default:
		return false
	}