我正试图在go中实现一组函数。上下文是一个事件服务器;我想阻止(或者至少警告)为一个事件多次添加相同的处理程序。Go中唯一函数的集合
我已阅读,地图是地道的,因为容易检查会员的套使用方法:
if _, ok := set[item]; ok {
// don't add item
} else {
// do add item
}
我遇到了一些麻烦,使用这种模式的功能虽然。这是我第一次尝试:
// this is not the actual signature
type EventResponse func(args interface{})
type EventResponseSet map[*EventResponse]struct{}
func (ers EventResponseSet) Add(r EventResponse) {
if _, ok := ers[&r]; ok {
// warn here
return
}
ers[&r] = struct{}{}
}
func (ers EventResponseSet) Remove(r EventResponse) {
// if key is not there, doesn't matter
delete(ers, &r)
}
很清楚为什么这不起作用:功能不引用类型在围棋,虽然有些人会告诉你他们。 I have proof,尽管我们不需要它,因为语言规范说除映射,切片和指针以外的所有东西都是按值传递的。
尝试2:
func (ers EventResponseSet) Add(r *EventResponse) {
// ...
}
这有几个问题:
任何显示eventResponse必须声明如下
fn := func(args interface{}){}
,因为你不能满足通常的方式声明的函数。根本无法传递闭包。
使用包装并不是一种选择,因为任何传递给包装的函数都会从包装中获得一个新地址 - 没有任何函数会被地址唯一标识,而所有这些仔细的计划都是徒劳的。
难道我不接受定义函数作为变量的解决方案吗?是否有另一个(好的)解决方案?
要清楚,我接受有些情况下我无法捕捉(关闭),这很好。我设想的用例是定义一堆处理程序,并且相对安全,我不会无意中将两个事件添加到同一事件两次,如果这是有道理的。
如果键类型是'* EventResponse',那将无法捕获两次添加相同的函数,因为你的键是一个指向任何变量指向函数的指针。你可能想看看'reflect'包 - 这可能会提供一种方法来做你想做的事。 –
函数不是[可比较的](https://golang.org/ref/spec#Comparison_operators)。您需要使用功能以外的其他功能作为关键。 –
我知道这些功能没有可比性。然而,[函数指针是](http://stackoverflow.com/a/9644797/1375316),这正是我想要做的。我的问题是函数不可寻址。你能提出一个很好的替代方案吗?可以从函数本身获得的东西,而不是由用户/应用程序定义的东西? – threeve