我正在尝试在 Go 中编写一个通知结构,它将保存一系列键及其各自的值,并且如果值低于阈值将触发通知。
当第一个样本低于阈值时,通知应该只触发一次,并且低于该值的其他样本不应再次触发,直到值升至阈值以上。
例如,假设我的阈值是 10,我发送了 15、14、11、10、... 9 的样本。发送 9 后,应触发通知。8、7、4 的进一步样本不应造成任何影响。以下样本如 5、6、7、9、10、11、14、30 不应执行任何操作。一旦样本再次低于 10:30、20、15、10、7... 必须发送另一个通知。
当多个 goroutines 操纵我的结构时,我遇到了问题。
我尝试使用 sync.Mutex 进行同步,还使用了 sync.Map,但没有成功。我觉得某处有参考副本或缓存,但我对 Go 太陌生了,无法找到问题所在。
为此,我创建了一个这样的结构:
type Notifier interface {
Send(message string)
}
type NotificationBoard struct {
mutex sync.Mutex
Last sync.Map
notifier Notifier
}
func (n *NotificationBoard) Init(notifier Notifier) {
n.notifier = notifier
}
// NotifyLess ...
func (n *NotificationBoard) NotifyLess(key string, value, threshold float64) {
n.mutex.Lock()
defer n.mutex.Unlock()
if value >= threshold {
fmt.Printf("NotificationBoard.NotifyLess %v (value >= threshold): %v >= %v\n", key, value, threshold)
n.Last.Store(key, value)
return
}
// value < threshold
if last, found := n.Last.Load(key); found == true {
fmt.Printf("NotificationBoard.NotifyLess %v (value < threshold): %v < %v : found %v\n", key, value, threshold, last)
if last.(float64) >= threshold { // first trigger
n.notifier.Send(fmt.Sprintf("%s < %v (%v)", key, threshold, value))
}
} else {
fmt.Printf("NotificationBoard.NotifyLess %v (value < threshold): %v < %v : not found\n", key, value, threshold)
// not found, started board as less
n.notifier.Send(fmt.Sprintf("%s < %v (%v)", key, threshold, value))
}
n.Last.Store(key, value)
return
}
我知道使用 sync.Mutex 或 sync.Map 应该就足够了,但上面的代码两者都有,因为它是我当前的(损坏的)版本。
为了测试,我设置了以下代码:
type dummy struct{}
func (d *dummy) Send(message string) {
fmt.Println("--------------> notifying", message)
}
func newBoard() *NotificationBoard {
notificationBoard := &NotificationBoard{}
notificationBoard.Init(&dummy{})
return notificationBoard
}
噜噜哒
当年话下
相关分类