ちりもつもればミルキーウェイ

好奇心に可処分時間が奪われる

Genericsをつかってcomparableなpointerの値が等価かどうか判定したいよ〜

はじめに

今回は軽めな回です。

そもそもpointerはcomparebleであり、面倒なことをせずとも == にて比較可能です。

https://go.dev/ref/spec#Comparison_operators

Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil. Pointers to distinct zero-size variables may or may not be equal.

なんですが、これは pointerの示すアドレスが一致したときにtrueを返す つくりであり、derefした値の同一性を確認したいときには使えません。(reflect.DeepEqual的な値まで追いかけて確認はしてくれない)

でまあ値比較したいときあるよねという話です。pointer同士の値の比較って地味に考えることがおおくて

  • 値があったらderefで比較したい
  • とはいえnilケアはしないとderefでpanicなったりする
  • なのでnilがからむ組み合わせはderef前にちゃんと評価してreturnしときたい

みたいなかんじで地味に面倒。

composite typeのpointerなら reflect.DeepEqual() などつかうんですが、compositeじゃないやつはもっとサクッと比較したいなーというモチベがあった

複数項目比較したいみたいになってくるとだいぶコードがしんどい感じになるので、こういうのこそgenericsでなぎ倒せるのではと思いちょっと書いてみた次第

本題

こんなかんじで動いた

func pointerValEqual[T comparable](x, y *T) bool {
    if (x == nil) != (y == nil) {
        return false
    }
    if x == nil {
        return true
    }
    return *x == *y
}

https://go.dev/play/p/5xrFAQrKrng

まずnil有無が等しいかしらべて、nil && nilならtrueを返しつつ、のこりは安全にderefできるので値で比較という感じです!

comparableな同じ型Tの比較に落とし込んでいてうまい感じに書けたのではという手応え!