Kubernetes API规范:为optional的字段使用pointer

首先请看一下kubernetes core的API代码:https://github.com/kubernetes...

我们可以发现,只要是 optional 的字段,那么必然是一个pointer:

    // nfs represents an NFS mount on the host that shares a pod's lifetime
    // More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
    // +optional
    NFS *NFSVolumeSource `json:"nfs,omitempty" protobuf:"bytes,7,opt,name=nfs"`

再比如:

    // volumeMode defines if a volume is intended to be used with a formatted filesystem
    // or to remain in raw block state. Value of Filesystem is implied when not included in spec.
    // +optional
    VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,8,opt,name=volumeMode,casttype=PersistentVolumeMode"`

这是为什么呢?

其实在kubernetes官方给出的API规约中,有这样一句话:https://github.com/kubernetes...

Therefore, we ask that pointers always be used with optional fields that do not have a built-in nil value.

翻译为:

我们要求没有内建nil值的optional字段,总是使用pointers.

首先我们需要了解使用pointer和没有使用pointer的区别,假设我们没有使用pointer:

type Apple struct {
    // +required
    Name string `json:"name"`
}

type Tree struct {
    // +optional
    Apple Apple `json:"apple"`
}

当我们想创建一个 “没有苹果的树”, 我们使用put如下json:

{}

但是由于apple字段并不是pointer,所以我们最终创建的是一个空结构体,最终存储(在etcd或者disk)的结构为:

{
    apple: {
        name: ""
    }
}

但是这个结构也可以表示一个“有苹果的树”,只不过苹果的名字为“”(空字符串)。

此时,“零值(zero value)”和“空(nil)”之间就有了歧义。 虽然我们可以在代码中添加一些规则来消除这种歧义,比如: 禁止创建名字为空字符串的苹果。
但是Kubernetes API规约中,也给出了3点原因,解释我们为什么最好在field是optional的情况下,使用pointer:

  1. 此类情况很多,实现者每一个都需要甄别和处理的话,过于劳心费神。
  2. 即使指定了 omitempty,编码器输出也不会省略结构,最后看起来就会乱糟糟的。
  3. 如果在客户端代码中使用go编码,且遵守了“optional->pointer”的规则,那么当遇到一个pointer的时候,我们也直接可以反推出这个field是optinal的,十分方便。

综上所述,如果你也觉得这条规范有道理的话,那么未来在编写或升级API的时候,遇到optional的时间,第一时间使用pointer吧!

你可能感兴趣的:(kubernetesapi)