github.com/niubaoshu/goutils@v0.0.0-20180828035119-e8e576f66c2b/deepclone.go (about) 1 // deepcopy makes deep copies of things. A standard copy will copy the 2 // pointers: deep copy copies the values pointed to. Unexported field 3 // values are not copied. 4 // 5 // Copyright (c)2014-2016, Joel Scoble (github.com/mohae), all rights reserved. 6 // License: MIT, for more details check the included LICENSE file. 7 package goutils 8 9 import ( 10 "reflect" 11 "unsafe" 12 ) 13 14 // Copy creates a deep copy of whatever is passed to it and returns the copy 15 // in an interface{}. The returned value will need to be asserted to the 16 // correct type. 17 func DeepClone(src interface{}) interface{} { 18 if src == nil { 19 return nil 20 } 21 22 // Make the interface a reflect.Value 23 original := reflect.ValueOf(src) 24 25 // Make a copy of the same type as the original. 26 cpy := reflect.New(original.Type()).Elem() 27 28 // Recursively copy the original. 29 copyRecursive(original, cpy) 30 31 //fmt.Println("original ", original) 32 //fmt.Println("copy", cpy) 33 // Return the copy as an interface. 34 return cpy.Interface() 35 } 36 37 // copyRecursive does the actual copying of the interface. It currently has 38 // limited support for what it can handle. Add as needed. 39 func copyRecursive(original, cpy reflect.Value) { 40 // handle according to original's Kind 41 switch original.Kind() { 42 case reflect.Ptr: 43 // Get the actual value being pointed to. 44 originalValue := original.Elem() 45 46 // if it isn't valid, return. 47 if !originalValue.IsValid() { 48 return 49 } 50 cpy.Set(reflect.New(originalValue.Type())) 51 copyRecursive(originalValue, cpy.Elem()) 52 53 case reflect.Interface: 54 // If this is a nil, don't do anything 55 if original.IsNil() { 56 return 57 } 58 // Get the value for the interface, not the pointer. 59 originalValue := original.Elem() 60 61 // Get the value by calling Elem(). 62 copyValue := reflect.New(originalValue.Type()).Elem() 63 copyRecursive(originalValue, copyValue) 64 cpy.Set(copyValue) 65 66 case reflect.Struct: 67 for i := 0; i < original.NumField(); i++ { 68 field := cpy.Type().Field(i) 69 copyRecursive(original.Field(i), 70 reflect.NewAt(field.Type, unsafe.Pointer(cpy.Field(i).UnsafeAddr())).Elem()) 71 } 72 73 case reflect.Slice: 74 if original.IsNil() { 75 return 76 } 77 // Make a new slice and copy each element. 78 cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap())) 79 for i := 0; i < original.Len(); i++ { 80 copyRecursive(original.Index(i), cpy.Index(i)) 81 } 82 83 case reflect.Map: 84 if original.IsNil() { 85 return 86 } 87 cpy.Set(reflect.MakeMap(original.Type())) 88 for _, oKey := range original.MapKeys() { 89 cKey := reflect.New(oKey.Type()).Elem() 90 oVal := original.MapIndex(oKey) 91 cVal := reflect.New(oVal.Type()).Elem() 92 copyRecursive(oKey, cKey) 93 copyRecursive(oVal, cVal) 94 cpy.SetMapIndex(cKey, cVal) 95 } 96 case reflect.Array: 97 for i := 0; i < original.Len(); i++ { 98 copyRecursive(original.Index(i), cpy.Index(i)) 99 } 100 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 101 cpy.SetInt(original.Int()) 102 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 103 cpy.SetUint(original.Uint()) 104 case reflect.Bool: 105 cpy.SetBool(original.Bool()) 106 case reflect.Float32, reflect.Float64: 107 cpy.SetFloat(original.Float()) 108 case reflect.Complex64, reflect.Complex128: 109 cpy.SetComplex(original.Complex()) 110 case reflect.String: 111 cpy.SetString(original.String()) 112 case reflect.UnsafePointer: 113 cpy.SetPointer(unsafe.Pointer(original.Pointer())) 114 } 115 }