什么是Cloner
Cloner是Kubernetes用来管理type对应的拷贝函数,自定义拷贝函数需要注册到Cloner中。Cloner定义在/pkg/conversion/cloner.go中:
1 2 3 4 5 6
| type Cloner struct { deepCopyFuncs map[reflect.Type]reflect.Value generatedDeepCopyFuncs map[reflect.Type]func(in interface{}, out interface{}, c *Cloner) error }
|
Cloner结构体只有deepCopyFuncs和generatedDeepCopyFuncs两个字段:
- deepCopyFuncs: 管理普通拷贝函数,通过RegisterDeepCopyFunc()方法注册;
- generatedDeepCopyFuncs: 管理自动生成的拷贝函数,通过RegisterGeneratedDeepCopyFunc()方法注册。
Cloner通过NewCloner()函数生成:
1 2 3 4 5 6 7 8 9 10 11 12 13
| func NewCloner() *Cloner { c := &Cloner{ deepCopyFuncs: map[reflect.Type]reflect.Value{}, generatedDeepCopyFuncs: map[reflect.Type]func(in interface{}, out interface{}, c *Cloner) error{}, } if err := c.RegisterDeepCopyFunc(byteSliceDeepCopy); err != nil { panic(err) } return c }
|
和Converter一样,我们分为注册方法和拷贝方法两个类别对Cloner的方法进行介绍。
注册方法
RegisterDeepCopyFunc()
RegisterDeepCopyFunc()可以把deepCopyFunc注册到Cloner的deepCopyFuncs中。deepCpyFuncs维持有类型和拷贝函数的map关系。
1 2 3 4 5 6 7 8 9 10 11
| func (c *Cloner) RegisterDeepCopyFunc(deepCopyFunc interface{}) error { fv := reflect.ValueOf(deepCopyFunc) ft := fv.Type() if err := verifyDeepCopyFunctionSignature(ft); err != nil { return err } c.deepCopyFuncs[ft.In(0)] = fv return nil }
|
RegisterGeneratedDeepCopyFunc()
RegisterGeneratedDeepCopyFunc()可以把GeneratedDeepCopyFunc注册到generatedDeepCopyFuncs中。generatedDeepCopyFuncs维持有类型和拷贝函数的关系。
1 2 3 4 5 6 7 8 9 10 11 12 13
| type GeneratedDeepCopyFunc struct { Fn func(in interface{}, out interface{}, c *Cloner) error InType reflect.Type } // Similar to RegisterDeepCopyFunc, but registers deep copy function that were // automatically generated. func (c *Cloner) RegisterGeneratedDeepCopyFunc(fn GeneratedDeepCopyFunc) error { c.generatedDeepCopyFuncs[fn.InType] = fn.Fn return nil }
|
拷贝方法
DeepCopy()
DeepCopy()为Cloner执行拷贝操作的入口,主要调用了deepCopy()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| func (c *Cloner) DeepCopy(in interface{}) (interface{}, error) { if in == nil { return nil, nil } inValue := reflect.ValueOf(in) outValue, err := c.deepCopy(inValue) if err != nil { return nil, err } return outValue.Interface(), nil }
|
deepCopy()
deepCopy()的流程如下:
- 获取待拷贝结构体值的类型;
- 尝试使用deepCopyFuncs中的拷贝函数进行拷贝;
- 尝试使用generatedDeepCopyFuncs中的拷贝函数进行拷贝;
- 使用defaultDeepCopy()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| func (c *Cloner) deepCopy(src reflect.Value) (reflect.Value, error) { inType := src.Type() switch src.Kind() { case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: if src.IsNil() { return src, nil } } if fv, ok := c.deepCopyFuncs[inType]; ok { return c.customDeepCopy(src, fv) } if fv, ok := c.generatedDeepCopyFuncs[inType]; ok { var outValue reflect.Value outValue = reflect.New(inType.Elem()) err := fv(src.Interface(), outValue.Interface(), c) return outValue, err } return c.defaultDeepCopy(src) } func (c *Cloner) customDeepCopy(src, fv reflect.Value) (reflect.Value, error) { outValue := reflect.New(src.Type().Elem()) args := []reflect.Value{src, outValue, reflect.ValueOf(c)} result := fv.Call(args)[0].Interface() if result == nil { return outValue, nil } return outValue, result.(error) }
|
defaultDeepCopy()
defaultDeepCopy()会根据待拷贝类型的不同采取不同的拷贝方法,这过程中可能是递归拷贝。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| func (c *Cloner) defaultDeepCopy(src reflect.Value) (reflect.Value, error) { switch src.Kind() { case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Uintptr: return src, fmt.Errorf("cannot deep copy kind: %s", src.Kind()) case reflect.Array: dst := reflect.New(src.Type()) for i := 0; i < src.Len(); i++ { copyVal, err := c.deepCopy(src.Index(i)) if err != nil { return src, errs } dst.Elem().Index(i).Set(copyVal) } return dst.Elem(), nil case reflect.Interface: if src.IsNil() { return src, nil } return c.deepCopy(src.Elem()) case reflect.Map: if src.IsNil() { return src, nil } dst := reflect.MakeMap(src.Type()) for _, k := range src.MapKeys() { copyVal, err := c.deepCopy(src.MapIndex(k)) if err != nil { return src, err } dst.SetMapIndex(k, copyVal) } return dst, nil case reflect.Ptr: if src.IsNil() { return src, nil } dst := reflect.New(src.Type().Elem()) copyVal, err := c.deepCopy(src.Elem()) if err != nil { return src, err } dst.Elem().Set(copyVal) return dst, nil case reflect.Slice: if src.IsNil() { return src, nil } dst := reflect.MakeSlice(src.Type(), 0, src.Len()) for i := 0; i < src.Len(); i++ { copyVal, err := c.deepCopy(src.Index(i)) if err != nil { return src, err } dst = reflect.Append(dst, copyVal) } return dst, nil case reflect.Struct: dst := reflect.New(src.Type()) for i := 0; i < src.NumField(); i++ { if !dst.Elem().Field(i).CanSet() { return src, nil } copyVal, err := c.deepCopy(src.Field(i)) if err != nil { return src, err } dst.Elem().Field(i).Set(copyVal) } return dst.Elem(), nil default: return src, nil } }
|
Demo
该Demo很简单,把结构体A的值aVal拷贝成copyVal。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package main import ( "fmt" "k8s.io/kubernetes/pkg/conversion" ) func main() { type NameMeta struct { Name string } type TypeMeta struct { Type string } type A struct { TypeMeta NameMeta } cloner := conversion.NewCloner() err := cloner.RegisterDeepCopyFunc( func(in *A, out *A, c *conversion.Cloner) error { copyTypeMeta, _ := c.DeepCopy(in.TypeMeta) copyNameMeta, _ := c.DeepCopy(in.NameMeta) out.TypeMeta = copyTypeMeta.(TypeMeta) out.NameMeta = copyNameMeta.(NameMeta) return nil }) if err != nil { fmt.Println("error occurs for cloner.RegisterDeepCopyFunc:", err) } aVal := &A{ TypeMeta: TypeMeta{"animal"}, NameMeta: NameMeta{"Cat"}} copyVal, _ := cloner.DeepCopy(aVal) fmt.Println(copyVal) }
|
结果:
1 2 3 4 5 6 7 8 9
| Clone *main.A use deepCopyFuncs *main.A Clone main.TypeMeta in defaultDeepCopy struct in defaultDeepCopy string Clone main.NameMeta in defaultDeepCopy struct in defaultDeepCopy string &{{animal} {Cat}}
|