package deepcopy
import (
"reflect"
)
func Copy[T any](v T) T {
return copyValue(reflect.ValueOf(v)).Interface().(T)
}
func copyValue(v reflect.Value) reflect.Value {
switch v.Type().Kind() {
case reflect.Array:
c := reflect.New(v.Type()).Elem()
for i := range v.Len() {
c.Index(i).Set(copyValue(v.Index(i)))
}
return c
case reflect.Map:
if v.IsNil() {
return v
}
c := reflect.MakeMap(v.Type())
for mr := v.MapRange(); mr.Next(); {
c.SetMapIndex(copyValue(mr.Key()), copyValue(mr.Value()))
}
return c
case reflect.Pointer:
if v.IsNil() {
return v
}
c := reflect.New(v.Type().Elem())
c.Elem().Set(copyValue(v.Elem()))
return c
case reflect.Slice:
if v.IsNil() {
return v
}
c := reflect.MakeSlice(v.Type(), v.Len(), v.Cap())
for i := range v.Len() {
c.Index(i).Set(copyValue(v.Index(i)))
}
return c
case reflect.Struct:
c := reflect.New(v.Type()).Elem()
for i := range v.NumField() {
if c.Field(i).CanSet() {
c.Field(i).Set(copyValue(v.Field(i)))
}
}
return c
default: return v
}
}