golangの日記

Go言語を中心にプログラミングについてのブログ

Go言語で関数が同じかどうか比較する

golang.png


定義した関数やそれを変数に代入したときに同じ関数かどうかの比較





==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
}