123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- // Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
- //
- // This Source Code Form is subject to the terms of the MIT License.
- // If a copy of the MIT was not distributed with this file,
- // You can obtain one at https://github.com/gogf/gf.
- // Package deepcopy makes deep copies of things using reflection.
- //
- // This package is maintained from: https://github.com/mohae/deepcopy
- package deepcopy
- import (
- "reflect"
- "time"
- )
- // Interface for delegating copy process to type
- type Interface interface {
- DeepCopy() interface{}
- }
- // 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
- }
- // Copy by type assertion.
- switch r := src.(type) {
- case
- int, int8, int16, int32, int64,
- uint, uint8, uint16, uint32, uint64,
- float32, float64,
- complex64, complex128,
- string,
- bool:
- return r
- default:
- if v, ok := src.(Interface); ok {
- return v.DeepCopy()
- }
- var (
- original = reflect.ValueOf(src) // Make the interface a reflect.Value
- dst = reflect.New(original.Type()).Elem() // Make a copy of the same type as the original.
- )
- // Recursively copy the original.
- copyRecursive(original, dst)
- // Return the copy as an interface.
- return dst.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() && original.IsValid() && !original.IsZero() {
- 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)
- }
- }
|