github.com/searKing/golang/go@v1.2.74/util/object/clone.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package object 6 7 import ( 8 "bytes" 9 "encoding/gob" 10 "reflect" 11 ) 12 13 // DeepCopys returns a interface consisting of the deeply copying elements. 14 // just clone public&clonable elems - upper case - name & IsCloneable()==true 15 func DeepClone(obj interface{}) (copy interface{}) { 16 if !IsNilable(obj) || !IsCloneable(obj) { 17 return obj 18 } 19 v := reflect.ValueOf(obj) 20 copyV := reflect.New(v.Type()).Elem() 21 deepClones(obj, copyV.Addr().Interface()) 22 return copyV.Interface() 23 } 24 25 // deepClones provides the method to creates a deep copy of whatever is passed to 26 // it and returns the copy in an interface. The returned value will need to be 27 // asserted to the correct type. 28 func deepClones(origin, copy interface{}) error { 29 var buf bytes.Buffer 30 if err := gob.NewEncoder(&buf).Encode(origin); err != nil { 31 return err 32 } 33 return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(copy) 34 } 35 36 // IsCloneable Returns {@code true} if the arguments are a chan or func field 37 // or pointer to chan or func 38 // and {@code false} otherwise. 39 func IsCloneable(obj interface{}) bool { 40 switch t := reflect.ValueOf(obj); t.Kind() { 41 // All basic types are easy: they are predefined. 42 case reflect.Bool: 43 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 44 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 45 case reflect.Float32, reflect.Float64: 46 case reflect.Complex64, reflect.Complex128: 47 case reflect.String: 48 case reflect.Interface: 49 case reflect.Array: 50 case reflect.Map: 51 case reflect.Slice: 52 case reflect.Struct: 53 default: 54 // If the field is a chan or func or pointer thereto, don't send it. 55 // That is, treat it like an unexported field. 56 for t.Kind() == reflect.Ptr { 57 t = t.Elem() 58 } 59 if t.Kind() == reflect.Chan || t.Kind() == reflect.Func { 60 return false 61 } 62 return true 63 } 64 return true 65 }