猿问

如何比较 Go 中的 2 个函数?

例如,我有要比较的函数列表:


http://play.golang.org/p/_rCys6rynf


type Action func(foo string)


type Handler struct {

  Get Action

  Post Action

}


var routes map[string]Handler


func Undefined(foo string) {

}


func Defined(foo string) {

}


func init() {

  routes = map[string]Handler{

    `/`: Handler{Defined,Undefined},

  }

}


func main() {

  for _, handler := range routes {

    if handler.Post != Undefined { 

      // do something

    } // invalid operation: (func(string))(handler.Post) != Undefined (func can only be compared to nil)



    if &handler.Post != &Undefined { 

      // do something 

    } // cannot take the address of Undefined

    // invalid operation: &handler.Post != &Undefined (mismatched types *Action and *func(string))

  }

}

比较两个函数是否相同的正确方法是什么?


ITMISS
浏览 373回答 3
3回答

精慕HU

在继续之前:您应该重构而不是比较函数值地址。规范:比较运算符:切片、映射和函数值不可比较。但是,作为特殊情况,切片、映射或函数值可以与预先声明的标识符进行比较nil。函数值不具有可比性。您可以做的是比较函数值的地址是否相同(不是保存函数值的变量的地址,而是函数值本身)。您不能获取 function 的地址,但是如果您将其与fmt包一起打印,则会打印其地址。所以你可以使用fmt.Sprintf()来获取一个函数值的地址。请参阅此示例(基于您的代码):hand := &Handler{Undefined, Defined}p1 := fmt.Sprintf("%v", Undefined)p2 := fmt.Sprintf("%v", hand.Get)fmt.Println("Expecting true:", p1 == p2)fmt.Println("Expecting false:", fmt.Sprintf("%v", Defined) == fmt.Sprintf("%v", hand.Get))fmt.Println("Expecting true:", fmt.Sprintf("%v", Defined) == fmt.Sprintf("%v", hand.Post))输出(在Go Playground上试试):Expecting true: trueExpecting false: falseExpecting true: true另一种选择是用于reflect.Value.Pointer()获取函数值的地址,这正是fmt包的作用fmt/print.go:func (p *pp) fmtPointer(value reflect.Value, verb rune) {    // ...    case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice,            reflect.UnsafePointer:        u = value.Pointer()    // ...}但是您应该重构而不是比较函数值地址。

30秒到达战场

没关系,找到答案:runtime.FuncForPC(reflect.ValueOf(handler.Post).Pointer()).Name() !=     runtime.FuncForPC(reflect.ValueOf(Undefined).Pointer()).Name()

墨色风雨

你不能比较功能。它需要存储到一个变量中,并将其作为指针引用。http://play.golang.org/p/sflsjjCHN5
随时随地看视频慕课网APP

相关分类

Go
我要回答