功能签名为类型

时间:2017-08-01 06:15:52

标签: go

我有一个定义为

的函数签名类型
type MessageListener func(msg *Message) bool

在结构中,我定义了以下函数,它基本上使用上面类型定义的函数签名注册一个Listener

func (wm *WM) AddListener(listener *MessageListener) error {
...
}

我的服务结构

type Service struct {
     ...
}

func (service *Service) receiveMessage(msg *Message) bool {
    ...
}

当我这样做时,为什么会出现不兼容的类型错误

wm.AddListener(&service.receiveMessage)

service.receiveMessage不具有MessageListener类型吗?

2 个答案:

答案 0 :(得分:2)

因为函数是引用,所以您不需要使用任何指针或尝试获取函数的地址 只需声明

func (wm *WM) AddListener(listener MessageListener) error {
...
}
// and get rid of taken address of function
wm.AddListener(service.receiveMessage)

答案 1 :(得分:1)

MessageListener已经是函数指针,因此您只需将AddListener定义为

func (wm *WM) AddListener(listener MessageListener) error {
    //...
}

然后可以通过调用wm.AddListener(service.receiveMessage)来注册侦听器。

来自Address operator的规格:

  

对于类型为T的操作数x,地址操作& x生成类型为* T到x的指针。操作数必须是可寻址的,即,变量,指针间接或切片索引操作;或可寻址结构操作数的字段选择器;或者可寻址数组的数组索引操作。作为可寻址性要求的例外,x也可以是(可能带括号的)复合文字。如果x的评估会导致运行时恐慌,那么& x的评估也会发生。

所以你不能获取函数/方法的地址。但是,您可以获取存储函数/方法的变量的地址。将侦听器声明为

是有效的
func (wm *WM) AddListener(listener *MessageListener) error {
    //...
}

但是在注册监听器时,请执行以下操作:

var fn MessageListener = service.receiveMessage
wm.AddListener(&fn)

并且在调用侦听器时:

msg := Message{//...}
(*wm.listener)(&msg)

添加了不必要的代码,用于将函数变量转换为指针,然后转换回函数变量。