surrealpatch/util/deep/deep.go

88 lines
1.8 KiB
Go
Raw Normal View History

2016-09-12 15:47:07 +00:00
// Copyright © 2016 Abcum Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package deep
import (
"reflect"
)
// Copy returns a deep copy of the source object.
func Copy(src interface{}) interface{} {
if src == nil {
return nil
}
prime := reflect.ValueOf(src)
clone := reflect.New(prime.Type()).Elem()
copy(prime, clone)
return clone.Interface()
}
func copy(prime, clone reflect.Value) {
switch prime.Kind() {
case reflect.Ptr:
value := prime.Elem()
if !value.IsValid() {
return
}
clone.Set(reflect.New(value.Type()))
copy(value, clone.Elem())
case reflect.Interface:
if prime.IsNil() {
return
}
value := prime.Elem()
alike := reflect.New(value.Type()).Elem()
copy(value, alike)
clone.Set(alike)
case reflect.Struct:
for i := 0; i < prime.NumField(); i++ {
if prime.Type().Field(i).PkgPath != "" {
continue
}
copy(prime.Field(i), clone.Field(i))
}
case reflect.Slice:
clone.Set(reflect.MakeSlice(prime.Type(), prime.Len(), prime.Cap()))
for i := 0; i < prime.Len(); i++ {
copy(prime.Index(i), clone.Index(i))
}
case reflect.Map:
clone.Set(reflect.MakeMap(prime.Type()))
for _, key := range prime.MapKeys() {
value := prime.MapIndex(key)
alike := reflect.New(value.Type()).Elem()
copy(value, alike)
clone.SetMapIndex(key, alike)
}
default:
clone.Set(prime)
}
}