text: // deepcopy makes deep copies of things. A standard copy will copy the
  // pointers: deep copy copies the values pointed to.  Unexported field
  // values are not copied.
  //
  // Copyright (c)2014-2016, Joel Scoble (github.com/mohae), all rights reserved.
  // License: MIT, for more details check the included LICENSE file.
  package deepcopy
  
  import (
  	"reflect"
  	"time"
  )
  
  // Interface for delegating copy process to type
  type Interface interface {
  	DeepCopy() interface{}
  }
  
  // Iface is an alias to Copy; this exists for backwards compatibility reasons.
  func Iface(iface interface{}) interface{} {
  	return Copy(iface)
  }
  
  // Copy creates a deep copy of whatever is passed to it and returns the copy
  // in an interface{}.  The returned value will need to be asserted to the
  // correct type.
  func Copy(src interface{}) interface{} {
  	if src == nil {
  		return nil
  	}
  
  	// Make the interface a reflect.Value
  	original := reflect.ValueOf(src)
  
  	// Make a copy of the same type as the original.
  	cpy := reflect.New(original.Type()).Elem()
  
  	// Recursively copy the original.
  	copyRecursive(original, cpy)
  
  	// Return the copy as an interface.
  	return cpy.Interface()
  }
  
  // copyRecursive does the actual copying of the interface. It currently has
  // limited support for what it can handle. Add as needed.
  func copyRecursive(original, cpy reflect.Value) {
  	// check for implement deepcopy.Interface
  	if original.CanInterface() {
  		if copier, ok := original.Interface().(Interface); ok {
  			cpy.Set(reflect.ValueOf(copier.DeepCopy()))
  			return
  		}
  	}
  
  	// handle according to original's Kind
  	switch original.Kind() {
  	case reflect.Ptr:
  		// Get the actual value being pointed to.
  		originalValue := original.Elem()
  
  		// if  it isn't valid, return.
  		if !originalValue.IsValid() {
  			return
  		}
  		cpy.Set(reflect.New(originalValue.Type()))
  		copyRecursive(originalValue, cpy.Elem())
  
  	case reflect.Interface:
  		// If this is a nil, don't do anything
  		if original.IsNil() {
  			return
  		}
  		// Get the value for the interface, not the pointer.
  		originalValue := original.Elem()
  
  		// Get the value by calling Elem().
  		copyValue := reflect.New(originalValue.Type()).Elem()
  		copyRecursive(originalValue, copyValue)
  		cpy.Set(copyValue)
  
  	case reflect.Struct:
  		t, ok := original.Interface().(time.Time)
  		if ok {
  			cpy.Set(reflect.ValueOf(t))
  			return
  		}
  		// Go through each field of the struct and copy it.
  		for i := 0; i < original.NumField(); i++ {
  			// The Type's StructField for a given field is checked to see if StructField.PkgPath
  			// is set to determine if the field is exported or not because CanSet() returns false
  			// for settable fields.  I'm not sure why.  -mohae
  			if original.Type().Field(i).PkgPath != "" {
  				continue
  			}
  			copyRecursive(original.Field(i), cpy.Field(i))
  		}
  
  	case reflect.Slice:
  		if original.IsNil() {
  			return
  		}
  		// Make a new slice and copy each element.
  		cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
  		for i := 0; i < original.Len(); i++ {
  			copyRecursive(original.Index(i), cpy.Index(i))
  		}
  
  	case reflect.Map:
  		if original.IsNil() {
  			return
  		}
  		cpy.Set(reflect.MakeMap(original.Type()))
  		for _, key := range original.MapKeys() {
  			originalValue := original.MapIndex(key)
  			copyValue := reflect.New(originalValue.Type()).Elem()
  			copyRecursive(originalValue, copyValue)
  			copyKey := Copy(key.Interface())
  			cpy.SetMapIndex(reflect.ValueOf(copyKey), copyValue)
  		}
  
  	default:
  		cpy.Set(original)
  	}
  }
  