获取事件处理函数指针地址问题
hexxv opened this issue · comments
我目前使用的V1版本,代码如下:
// eventbus\nats\consumer.go
func (c *consumer) addHandler(handler eventbus.EventHandler) int {
pointer := reflect.ValueOf(handler).Pointer()
c.rw.Lock()
defer c.rw.Unlock()
c.handlers[pointer] = handler
return len(c.handlers)
}
经调试发现:
// eventbus\nats\consumer.go
pointer := reflect.ValueOf(handler).Pointer() // pointer总是返回同一个值
问题:
pointer总是返回同一个值
这将导致:同一个 topic,注册两个处理函数,后注册的会顶掉先注册的。
于是,我在V2发现了这个变动, 代码如下:
// 添加处理器
func (c *consumer) addHandler(handler eventbus.EventHandler) int {
pointer := reflect.ValueOf(handler).Pointer()
c.rw.Lock()
defer c.rw.Unlock()
if _, ok := c.handlers[pointer]; !ok {
c.handlers[pointer] = make([]eventbus.EventHandler, 0, 1)
}
c.handlers[pointer] = append(c.handlers[pointer], handler)
return len(c.handlers[pointer])
}
疑问点:
- 取pointer的目的? 看上去,V1版本是保证同一个处理函数无论注册多少次只调用一次, V2版本变更为 同一个处理函数注册n次调用n次。
- 个人愚见:v2版本看上去像是作者发现v1版本的问题后采用了变更设计的解决方案(我今天使用v1版本刚好遇到了这个问题),如果仅仅是解决V1版本的问题,好像修改一下就可以了:
// eventbus\nats\consumer.go
func (c *consumer) addHandler(handler eventbus.EventHandler) int {
// pointer := reflect.ValueOf(handler).Pointer()
pointer := reflect.ValueOf(unsafe.Pointer(&handler)).Pointer()
c.rw.Lock()
defer c.rw.Unlock()
c.handlers[pointer] = handler
return len(c.handlers)
}
感谢你提出的问题和解决方案。v2版本的初衷确实是为了一个事件同时被多个订阅函数进行处理。当时还考虑到取消订阅的API,因而采用了slice的的方案来存入多个函数。但目前的取消订阅的API会出现一个取消全部都取消的问题,因此后续会对该API进行优化,到时候会采用你的方案来进行处理。