Goで関数が同一かどうか調べる
Goの仕様として関数同士の比較はできないことはドキュメント等にも明記されているけど、何か抜け道はないのか。調べたが、Go 1.22時点ではどうやってもジェネリックな関数を安全に比較できない。
一般的な関数やメソッドの場合
Section titled “一般的な関数やメソッドの場合”普通の関数やメソッドであれば、reflectやruntimeを使えば関数アドレスで比較できる。
reflectを使う方法
Section titled “reflectを使う方法”方法はいくつかある。
reflect.ValueOf(f).Pointer()uintptr(reflect.ValueOf(f).UnsafePointer())どちらを使えばいいのかについては、reflect.Pointerのドキュメントに
It’s preferred to use
uintptr(Value.UnsafePointer())to get the equivalent result.
とある。
runtimeを使う方法
Section titled “runtimeを使う方法”runtime.FuncForPCでメモリアドレスから関数の情報(runtime.Func)を取得できる。
runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Entry()型パラメータを持つ関数の場合
Section titled “型パラメータを持つ関数の場合”ジェネリックな関数の場合、Goの関数アドレスは型パラメータ毎に別の型として扱われるので、上記の方法では型パラメータごとに異なるアドレスを取得してしまって関数アドレスによる比較が失敗する。