From 564187cc4a169f24f22de3d34c715e5eec450152 Mon Sep 17 00:00:00 2001 From: Weixie Cui Date: Sat, 9 May 2026 21:44:45 +0800 Subject: [PATCH] event: make nil available --- event/feedof.go | 2 +- event/feedof_test.go | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/event/feedof.go b/event/feedof.go index 4a24e37f12..6fc7d67cad 100644 --- a/event/feedof.go +++ b/event/feedof.go @@ -88,7 +88,7 @@ func (f *FeedOf[T]) remove(sub *feedOfSub[T]) { // Send delivers to all subscribed channels simultaneously. // It returns the number of subscribers that the value was sent to. func (f *FeedOf[T]) Send(value T) (nsent int) { - rvalue := reflect.ValueOf(value) + rvalue := reflect.ValueOf(&value).Elem() f.once.Do(f.init) <-f.sendLock diff --git a/event/feedof_test.go b/event/feedof_test.go index 846afc9ee1..e114adba71 100644 --- a/event/feedof_test.go +++ b/event/feedof_test.go @@ -70,6 +70,28 @@ func TestFeedOf(t *testing.T) { 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) { var ( feed FeedOf[int]