什么是Cloner

Cloner是Kubernetes用来管理type对应的拷贝函数,自定义拷贝函数需要注册到Cloner中。Cloner定义在/pkg/conversion/cloner.go中:

1
2
3
4
5
6
// Cloner knows how to copy one type to another.
type Cloner struct {
// Map from the type to a function which can do the deep copy.
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
// NewCloner creates a new Cloner object.
func NewCloner() *Cloner {
c := &Cloner{
deepCopyFuncs: map[reflect.Type]reflect.Value{},
generatedDeepCopyFuncs: map[reflect.Type]func(in interface{}, out interface{}, c *Cloner) error{},
}
//***注册byte类型拷贝函数***//
if err := c.RegisterDeepCopyFunc(byteSliceDeepCopy); err != nil {
// If one of the deep-copy functions is malformed, detect it immediately.
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)
//***类型 reflect.Value 有一个方法 Type(),它会返回一个 reflect.Type 类型的对象***//
ft := fv.Type()
if err := verifyDeepCopyFunctionSignature(ft); err != nil {
return err
}
//***deepCopyFuncs的key为函数的第一个参数的类型***//
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
// GeneratedDeepCopyFunc bundles an untyped generated deep-copy function of a type
// with a reflection type object used as a key to lookup the deep-copy function.
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
// DeepCopy will perform a deep copy of a given object.
func (c *Cloner) DeepCopy(in interface{}) (interface{}, error) {
// Can be invalid if we run DeepCopy(X) where X is a nil interface type.
// For example, we get an invalid value when someone tries to deep-copy
// a nil labels.Selector.
// This does not occur if X is nil and is a pointer to a concrete type.
if in == nil {
return nil, nil
}
//***获取第一个参数的类型,如<float64 Value>***//
inValue := reflect.ValueOf(in)
//***进行克隆***//
outValue, err := c.deepCopy(inValue)
if err != nil {
return nil, err
}
return outValue.Interface(), nil
}

deepCopy()

deepCopy()的流程如下:

  1. 获取待拷贝结构体值的类型;
  2. 尝试使用deepCopyFuncs中的拷贝函数进行拷贝;
  3. 尝试使用generatedDeepCopyFuncs中的拷贝函数进行拷贝;
  4. 使用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
    }
    }
    //***从deepCopyFuncs中获取拷贝函数***//
    if fv, ok := c.deepCopyFuncs[inType]; ok {
    return c.customDeepCopy(src, fv)
    }
    //***从generatedDeepCopyFuncs中获取拷贝函数***//
    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
    }
    //***使用defaultDeepCopy()***//
    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()
    // This convolution is necessary because nil interfaces won't convert
    // to error.
    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
//***根据src的类型进行拷贝,src的类型一般为复杂类型***//
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
}
//***reflect.New()返回的是指针***//
dst := reflect.New(src.Type().Elem())
copyVal, err := c.deepCopy(src.Elem())
if err != nil {
return src, err
}
//***设置dst的值***//
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() {
// Can't set private fields. At this point, the
// best we can do is a shallow copy. For
// example, time.Time is a value type with
// private members that can be shallow copied.
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:
// Value types like numbers, booleans, and strings.
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 //执行copyVal, _ := cloner.DeepCopy(aVal),开始拷贝
use deepCopyFuncs *main.A //*main.A的拷贝函数有注册,所以使用deepCopyFuncs中的拷贝函数进行拷贝
Clone main.TypeMeta //拷贝函数中执行copyTypeMeta, _ := c.DeepCopy(in.TypeMeta),开始拷贝in.TypeMeta
in defaultDeepCopy struct //未注册*main.TypeMeta的拷贝函数,所以执行defaultDeepCopy(),需要拷贝的是struct,则递归拷贝字段
in defaultDeepCopy string //未注册*string的拷贝函数,所以执行defaultDeepCopy(),完成string的拷贝
Clone main.NameMeta //拷贝函数中执行copyNameMeta, _ := c.DeepCopy(in.NameMeta),开始拷贝in.NameMeta
in defaultDeepCopy struct //未注册*main.NameMeta的拷贝函数,所以执行defaultDeepCopy(),需要拷贝的是struct,则递归拷贝字段
in defaultDeepCopy string //未注册*string的拷贝函数,所以执行defaultDeepCopy(),完成string的拷贝
&{{animal} {Cat}} //打印copyVal