github.com/songzhibin97/gkit@v1.2.13/tools/deepcopy/deepcopy.go (about)

     1  package deepcopy
     2  
     3  import (
     4  	"github.com/songzhibin97/gkit/tools"
     5  	"reflect"
     6  )
     7  
     8  func deepCopy(dst, src reflect.Value) {
     9  	switch src.Kind() {
    10  	case reflect.Interface:
    11  		value := src.Elem()
    12  		if !value.IsValid() {
    13  			return
    14  		}
    15  		newValue := reflect.New(value.Type()).Elem()
    16  		deepCopy(newValue, value)
    17  		dst.Set(newValue)
    18  	case reflect.Ptr:
    19  		value := src.Elem()
    20  		if !value.IsValid() {
    21  			return
    22  		}
    23  		dst.Set(reflect.New(value.Type()))
    24  		deepCopy(dst.Elem(), value)
    25  	case reflect.Map:
    26  		dst.Set(reflect.MakeMap(src.Type()))
    27  		keys := src.MapKeys()
    28  		for _, key := range keys {
    29  			value := src.MapIndex(key)
    30  			newValue := reflect.New(value.Type()).Elem()
    31  			deepCopy(newValue, value)
    32  			dst.SetMapIndex(key, newValue)
    33  		}
    34  	case reflect.Slice:
    35  		dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap()))
    36  		for i := 0; i < src.Len(); i++ {
    37  			deepCopy(dst.Index(i), src.Index(i))
    38  		}
    39  	case reflect.Struct:
    40  		typeSrc := src.Type()
    41  		for i := 0; i < src.NumField(); i++ {
    42  			value := src.Field(i)
    43  			tag := typeSrc.Field(i).Tag
    44  			if value.CanSet() && tag.Get("gkit") != "-" {
    45  				deepCopy(dst.Field(i), value)
    46  			}
    47  		}
    48  	default:
    49  		dst.Set(src)
    50  	}
    51  }
    52  
    53  func DeepCopy(dst, src interface{}) error {
    54  	dstT, srcT := reflect.TypeOf(dst), reflect.TypeOf(src)
    55  	if dstT != srcT {
    56  		return tools.ErrorNoEquals
    57  	}
    58  	if srcT.Kind() != reflect.Ptr {
    59  		return tools.ErrorMustPtr
    60  	}
    61  	dstV, srcV := reflect.ValueOf(dst).Elem(), reflect.ValueOf(src).Elem()
    62  	if !dstV.IsValid() || !srcV.IsValid() {
    63  		return tools.ErrorInvalidValue
    64  	}
    65  	deepCopy(dstV, srcV)
    66  	return nil
    67  }
    68  
    69  func Clone(v interface{}) interface{} {
    70  	dst := reflect.New(reflect.TypeOf(v).Elem())
    71  	deepCopy(dst, reflect.ValueOf(v))
    72  	return dst.Interface()
    73  }