Zenn
🌊

k8s.io/utils/ptr の使い道

に公開

Go で Pointer を操作したい場合に "k8s.io/utils/ptr" が便利なので使って欲しいという気持ちで書きました!

https://pkg.go.dev/k8s.io/utils/ptr

Deref

func Deref[T any](ptr *T, def T) T

渡された ptr の T Pointer を Dereference し nil の場合は def を返す関数です。

例えば k8s Job の suspend で処理を変更したい場合

ptr.Deref を使用しない
var job batchv1Job
_ := k8sClient.Get(context.BackGround(), client.ObjectKeyFromObject(hoge), &job)
if job.Spec.Suspend != nil && *job.Spec.Suspend {
  // do something when job is suspended.
}

ptr.Deref を使用することで、 余計な nil チェックなどが消え簡潔に書くことができます。

ptr.Deref を使用する
var job batchv1.Job
_ := k8sClient.Get(context.BackGround(), client.ObjectKeyFromObject(hoge), &job)
if ptr.Deref(job.Spec.Suspend, false) {
  // do something when job is suspended.
}

To

func To[T any](v T) *T

渡された v の Pointer を返す関数です。

そのままですが、int や defined type の場合は型指定できるのでわざわざコンバートする必要はありません。

余計な Convert が含まれている
type Hoge string

pointerInt := ptr.To(int32(10))
pointerDefinedType := ptr.To(Hoge("hoge"))

ではなく

type Hoge string
pointerInt := ptr.To[int32](10)
pointerDefinedType := ptr.To[Hoge]("hoge")

Equal

func Equal[T comparable](a, b *T) bool

a と b を比較する関数です、引数に Pointer を渡すことができます。

例えば Custom Controller などで古い Job と新たな Job の suspend を比較して変更がある場合は Condition を変えたい場合

if !ptr.Equal(oldJob.Spec.Suspend, newJob.Spec.Suspend) {
  // set new condition.
}

AllPtrFieldsNil

func AllPtrFieldsNil(obj interface{}) bool

名前の通り構造体のすべての Pointer Field が nil かどうかを判定する関数です。

ほぼ使う場面はないと思いますが Default 値を設定したい場合などに使えます。

実際に Kubernetes では Volume に EmptyDir を設定する際に使われています。

func SetDefaults_Volume(obj *v1.Volume) {
	if ptr.AllPtrFieldsNil(&obj.VolumeSource) {
		obj.VolumeSource = v1.VolumeSource{
			EmptyDir: &v1.EmptyDirVolumeSource{},
		}
	}
	if utilfeature.DefaultFeatureGate.Enabled(features.ImageVolume) && obj.Image != nil && obj.Image.PullPolicy == "" {
		// PullPolicy defaults to Always if :latest tag is specified, or IfNotPresent otherwise.
		_, tag, _, _ := parsers.ParseImageName(obj.Image.Reference)
		if tag == "latest" {
			obj.Image.PullPolicy = v1.PullAlways
		} else {
			obj.Image.PullPolicy = v1.PullIfNotPresent
		}
	}
}

まとめ

"k8s.io" にはいろいろ便利なものがあるのでメモがてら書き留めようと思って書きました。

Go で Pointer を操作したい場合に便利なので使いましょう!(2回目)

Discussion

ログインするとコメントできます