package observer import ( "reflect" "sync" ) // Subject 被观察者 type Subject struct { observers []Observer in chan any mu sync.RWMutex once sync.Once } // Observer 观察者 chan type Observer chan any // NewSubject 获取被观察者实例 func NewSubject() Subject { return Subject{in: make(chan any)} } // Attach 观察者绑定 func (s *Subject) Attach(obs ...Observer) { s.mu.Lock() defer s.mu.Unlock() s.observers = append(s.observers, obs...) } // Detach 观察者解绑 func (s *Subject) Detach(obs Observer) { s.mu.Lock() defer s.mu.Unlock() for i, o := range s.observers { if o == obs { s.observers = append(s.observers[:i], s.observers[i+1:]...) close(obs) break } } } // Notify 通知观察者 func (s *Subject) Notify(data any) { // fanout 只启动一次,避免每次通知重复启动协程 s.once.Do(func() { go s.fanOut(s.in) }) s.in <- data } // fanOut 扇出模式实现 func (s *Subject) fanOut(ch <-chan interface{}) { // 绑定输入 chan 的 reflect.SelectCase cases := []reflect.SelectCase{ {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)}, } for { _, value, ok := reflect.Select(cases) // 从输入 chan 中读取数据 if !ok { // 输入 channel 被关闭 return } // 输入 channel 接收到数据 s.mu.RLock() for _, o := range s.observers { o <- value.Interface() // 放入到输出 chan 中,同步方式 } s.mu.RUnlock() } }