Go言語で関数が同じかどうか比較する
定義した関数やそれを変数に代入したときに同じ関数かどうかの比較
==
や reflect.DeepEqual
では比較できない。==
は nil かどうかをしか判定できない
package main import ( "fmt" "reflect" ) func A() {} func main() { fn := A fmt.Println(fn == A) // invalid operation: fn == A (func can only be compared to nil) fmt.Println(reflect.DeepEqual(fn, A)) // false }
reflect
を使ってポインタで比較するとできる。
package main import ( "fmt" "reflect" ) func A() {} func B() {} func main() { fn := A p1 := reflect.ValueOf(fn).Pointer() p2 := reflect.ValueOf(A).Pointer() fmt.Println(p1 == p2) // true p1 = reflect.ValueOf(A).Pointer() p2 = reflect.ValueOf(A).Pointer() fmt.Println(p1 == p2) // true p1 = reflect.ValueOf(fn).Pointer() p2 = reflect.ValueOf(B).Pointer() fmt.Println(p1 == p2) // false }
同じことを構造体で試すと以下のようになる
package main import ( "fmt" "reflect" ) type A struct {} func (a A) B() {} func (a A) C() {} func main() { fn1 := A{}.B fn2 := A{}.B fn3 := A{}.C fn4 := new(A).B fn5 := new(A).C p1 := reflect.ValueOf(fn1).Pointer() p2 := reflect.ValueOf(fn2).Pointer() p3 := reflect.ValueOf(fn3).Pointer() p4 := reflect.ValueOf(fn4).Pointer() p5 := reflect.ValueOf(fn5).Pointer() fmt.Println(p1 == p2) // true fmt.Println(p1 == p3) // false fmt.Println(p1 == p4) // true fmt.Println(p1 == p5) // false }