如何比较Go中的2个函数? [英] How to compare 2 functions in Go?

查看:608
本文介绍了如何比较Go中的2个函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

  type Action func (foo字符串)

类型处理程序结构{
获取操作
发布操作
}

var routes map [string] Handler
$ b $ func未定义的(foo字符串){
}

func定义的(foo字符串){
}

func init {
routes = map [string] Handler {
`/`:Handler {Defined,Undefined},
}
}

func main() {
for _,handler:= range routes {
if handler.Post!= Undefined {
//做某事
} //无效操作:(func(string)) (handler.Post)!=未定义(func只能与零比较)


if& handler.Post!=& Undefined {
// do something
} //不能取未定义的
的地址//无效的操作:& handler.Pos t!=& Undefined(不匹配的类型*动作和* func(字符串))
}
}

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

解决方案

你应该重构,而不是比较函数值地址。



规格:比较运算符:


切片,贴图和函数值不具有可比性。然而,作为一种特殊情况,片段,映射或函数值可以与预先标识的标识符 nil

$进行比较b
$ b

功能值不具有可比性。你可以做的是比较函数值的地址是否相同(不是保存函数值的变量的地址,而是函数值本身)。

你无法获取函数的地址,但是如果你使用 fmt 包,它会打印它的地址。因此,您可以使用 fmt.Sprintf() 获取函数值的地址。



请参阅此示例(根据您的代码):

< $ b $ p> hand:=& Handler {Undefined,Defined}
p1:= fmt.Sprintf(%v,未定义)
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 ):

 期待真实:真实
期待假:假
期待真实:真

另一个选择是使用 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()
// ...
}

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


For example I have list of functions that I want to compare:

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

What is the correct way to compare if two functions are the same?

解决方案

Before going further: you should refactor and not compare function value addresses.

Spec: Comparison operators:

Slice, map, and function values are not comparable. However, as a special case, a slice, map, or function value may be compared to the predeclared identifier nil.

Function values are not comparable. What you may do is compare if the addresses of the function values are the same (not the address of variables holding function values, but the function values themselves).

You can't take the address of a function, but if you print it with the fmt package, it prints its address. So you can use fmt.Sprintf() to get the address of a function value.

See this example (based on your code):

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

Output (try it on the Go Playground):

Expecting true: true
Expecting false: false
Expecting true: true

Another option would be to use reflect.Value.Pointer() to get the address of the function values, this is exactly what the fmt package does: 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()
    // ...
}

But you should refactor and not compare function value addresses.

这篇关于如何比较Go中的2个函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆