一尘不染

如何在Go中比较2个功能?

go

例如,我有要比较的功能列表:

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

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


阅读 191

收藏
2020-07-02

共1个答案

一尘不染

在继续之前:您应该重构而不是比较函数值地址。

规格:比较运算符:

切片,贴图和函数值不可比较。但是,在特殊情况下,可以将切片,映射或函数值与预先声明的标识符进行比较nil

函数值不可比。如果功能值的地址相同(不是保存功能值的变量的地址,而是功能值本身),则可以进行比较。

您不能使用函数的地址,但是如果您将其与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: true
Expecting false: false
Expecting 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()
    // ...
}

但是您应该重构而不是比较函数值地址。

2020-07-02