Documentation
¶
Overview ¶
Example ¶
package main import ( "context" "fmt" "time" "github.com/egustafson/sandbox/go/notifier" ) func noticeListener(ch <-chan notifier.Notice) { fmt.Println("listener: started") for notice := range ch { msg, ok := notice.(string) if !ok { fmt.Println("listener: received non-string notice") } else { fmt.Printf("listener: %s\n", msg) } } fmt.Println("listener: exiting") } func noticeCallback(notice notifier.Notice) { msg, ok := notice.(string) if !ok { fmt.Println("cb: received non-string notice") } else { fmt.Printf("cb: %s\n", msg) } } func main() { fmt.Println("") ctx, cancel := context.WithCancel(context.Background()) // no defer cancel() - we explicitly cancel() in this func n := notifier.NewNotifier() n.RegCallback(ctx, noticeCallback) n.Notify("[ only callback registered ]") go noticeListener(n.ListenerChan(ctx)) n.Notify("[ both cb and chan registered ]") go noticeListener(n.ListenerChan(context.Background())) // another listener, no ctx cancel n.Notify("[ second notice ]") time.Sleep(time.Millisecond) // let things settle a bit cancel() n.Notify("[ post cancel() notice ]") n.Close() // show Close() can be invoked after all listeners/cb's are canceled. time.Sleep(time.Millisecond) // let things settle a bit fmt.Println("Example() ending") }
Output: cb: [ only callback registered ] cb: [ both cb and chan registered ] listener: started listener: [ both cb and chan registered ] listener: started listener: [ second notice ] listener: [ second notice ] cb: [ second notice ] listener: exiting listener: [ post cancel() notice ] listener: exiting Example() ending
Example (Blocking) ¶
ExampleBlocking demonstrates the case where the listener chan blocks long enough to be "problematic" and the Notify() routine spins the notice out into a separate goroutine.
package main import ( "context" "fmt" "time" "github.com/egustafson/sandbox/go/notifier" ) func noticeListener(ch <-chan notifier.Notice) { fmt.Println("listener: started") for notice := range ch { msg, ok := notice.(string) if !ok { fmt.Println("listener: received non-string notice") } else { fmt.Printf("listener: %s\n", msg) } } fmt.Println("listener: exiting") } func main() { n := notifier.NewNotifier() ctx := context.Background() ch := n.ListenerChan(ctx) // get the chan but don't consume from it yet. n.Notify("[ msg 1 ]") n.Notify("[ msg 2 ]") // <-- this message should spawn a goroutine n.Notify("[ msg 3 ]") // <-- another goroutine ==> possible out of order deivery go noticeListener(ch) // now the messages drain, and print time.Sleep(time.Millisecond) // let things settle n.Close() time.Sleep(time.Millisecond) // let things settle, again fmt.Println("ExampleBlocking() ending") }
Output: timeout: deferring notice timeout: deferring notice listener: started listener: [ msg 1 ] listener: [ msg 2 ] listener: [ msg 3 ] listener: exiting ExampleBlocking() ending
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Notifier ¶
type Notifier interface { ListenerChan(ctx context.Context) <-chan Notice RegCallback(ctx context.Context, callback NotifyCallbackFn) Notify(notice Notice) Close() }
func NewNotifier ¶
func NewNotifier() Notifier
type NotifyCallbackFn ¶
type NotifyCallbackFn func(notice Notice)
Click to show internal directories.
Click to hide internal directories.