Skip to content

Instantly share code, notes, and snippets.

@bprosnitz
Created January 20, 2015 19:02
Show Gist options
  • Save bprosnitz/fb9c0b8e7f461245442e to your computer and use it in GitHub Desktop.
Save bprosnitz/fb9c0b8e7f461245442e to your computer and use it in GitHub Desktop.
Deep Copy
func deepCopy(rv reflect.Value) reflect.Value {
switch rv.Kind() {
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.String:
return rv
case reflect.Slice:
if rv.IsNil() {
return rv
}
sliceCpy := reflect.MakeSlice(rv.Type(), rv.Len(), rv.Cap())
for i := 0; i < sliceCpy.Len(); i++ {
sliceCpy.Index(i).Set(deepCopy(rv.Index(i)))
}
return sliceCpy
case reflect.Array:
arrCpy := reflect.New(rv.Type()).Elem()
for i := 0; i < arrCpy.Len(); i++ {
arrCpy.Index(i).Set(deepCopy(rv.Index(i)))
}
return arrCpy
case reflect.Map:
if rv.IsNil() {
return rv
}
mapCpy := reflect.MakeMap(rv.Type())
for _, key := range rv.MapKeys() {
mapCpy.SetMapIndex(key, deepCopy(rv.MapIndex(key)))
}
return mapCpy
case reflect.Struct:
structCpy := reflect.New(rv.Type()).Elem()
for i := 0; i < rv.NumField(); i++ {
for _, r := range rv.Type().Field(i).Name {
if !unicode.IsUpper(r) {
panic(fmt.Sprintf("Unexported field name on type %v: %s", rv.Type(), rv.Type().Field(i).Name))
}
break
}
structCpy.Field(i).Set(deepCopy(rv.Field(i)))
}
return structCpy
case reflect.Interface, reflect.Ptr:
if rv.IsNil() {
return rv
}
slice := reflect.MakeSlice(reflect.SliceOf(rv.Type()), 1, 1)
cpy := slice.Index(0)
cpy.Set(deepCopy(rv.Elem()))
return cpy
default:
panic(fmt.Sprintf("Unimplemented kind: %v", rv.Kind()))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment