例如,我有要比较的功能列表:
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)) } }
如果两个函数相同,比较的正确方法是什么?
在继续之前:您应该重构而不是比较函数值地址。
规格:比较运算符:
切片,贴图和函数值不可比较。但是,在特殊情况下,可以将切片,映射或函数值与预先声明的标识符进行比较nil。
nil
函数值不可比。如果功能值的地址相同(不是保存功能值的变量的地址,而是功能值本身),则可以进行比较。
您不能使用函数的地址,但是如果您将其与fmt包一起打印,它将打印其地址。这样就可以fmt.Sprintf()用来获取函数值的地址。
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:
reflect.Value.Pointer()
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() // ... }
但是您应该重构而不是比较函数值地址。