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

首先请看一下kubernetes core的API代码:https://github.com/kubernetes...
【Kubernetes API规范(为optional的字段使用pointer)】我们可以发现,只要是 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吧!

    推荐阅读