event: make nil available

This commit is contained in:
Weixie Cui 2026-05-09 21:44:45 +08:00
parent 1abbae239d
commit 564187cc4a
2 changed files with 23 additions and 1 deletions

View file

@ -88,7 +88,7 @@ func (f *FeedOf[T]) remove(sub *feedOfSub[T]) {
// Send delivers to all subscribed channels simultaneously. // Send delivers to all subscribed channels simultaneously.
// It returns the number of subscribers that the value was sent to. // It returns the number of subscribers that the value was sent to.
func (f *FeedOf[T]) Send(value T) (nsent int) { func (f *FeedOf[T]) Send(value T) (nsent int) {
rvalue := reflect.ValueOf(value) rvalue := reflect.ValueOf(&value).Elem()
f.once.Do(f.init) f.once.Do(f.init)
<-f.sendLock <-f.sendLock

View file

@ -70,6 +70,28 @@ func TestFeedOf(t *testing.T) {
done.Wait() done.Wait()
} }
// TestFeedOfSendNilAnySucceeds is a regression check: FeedOf[any].Send(nil) used to fail
// (panic from Invalid reflect.Value on reflect.SelectCase, or silent non-delivery from
// TrySend) because nil stored in interface{} does not satisfy reflect.ValueOf(value).Valid().
// Send must succeed and deliver nil to every subscriber.
func TestFeedOfSendNilAnySucceeds(t *testing.T) {
var feed FeedOf[any]
ch1 := make(chan any, 1)
ch2 := make(chan any, 1)
defer feed.Subscribe(ch1).Unsubscribe()
defer feed.Subscribe(ch2).Unsubscribe()
if nsent := feed.Send(nil); nsent != 2 {
t.Fatalf("Send(nil) nsent=%d, want 2 (failed delivery before reflect fix)", nsent)
}
for i, ch := range []chan any{ch1, ch2} {
got := <-ch
if got != nil {
t.Fatalf("subscriber %d: got %#v, want nil", i, got)
}
}
}
func TestFeedOfSubscribeSameChannel(t *testing.T) { func TestFeedOfSubscribeSameChannel(t *testing.T) {
var ( var (
feed FeedOf[int] feed FeedOf[int]