// 状态订阅发布:将 ScanService 的状态变更实时推送给订阅者(WebSocket 等)。 package service import "sync" // StatusListener 状态订阅通道(缓冲 1,保底容纳一条未消费状态) type StatusListener chan ScanStatus // StatusHub 管理状态订阅者;发布时若消费者来不及消费则丢弃旧消息, // 保证订阅者拿到的始终是最新状态。 type StatusHub struct { mu sync.RWMutex subs map[StatusListener]struct{} } // NewStatusHub 创建状态订阅中心 func NewStatusHub() *StatusHub { return &StatusHub{subs: make(map[StatusListener]struct{})} } // Subscribe 注册订阅,返回频道与取消函数。取消后频道被关闭,写方需停止发送。 func (h *StatusHub) Subscribe() (StatusListener, func()) { h.mu.Lock() defer h.mu.Unlock() ch := make(StatusListener, 1) h.subs[ch] = struct{}{} return ch, func() { h.mu.Lock() if _, ok := h.subs[ch]; ok { delete(h.subs, ch) close(ch) } h.mu.Unlock() } } // Publish 向所有订阅者推送最新状态(非阻塞;缓冲满时覆盖为最新状态) func (h *StatusHub) Publish(st ScanStatus) { h.mu.RLock() defer h.mu.RUnlock() for ch := range h.subs { select { case ch <- st: default: select { case <-ch: default: } ch <- st } } }