Skip to content

Instantly share code, notes, and snippets.

@abdivasiyev
Created August 12, 2026 09:30
Show Gist options
  • Select an option

  • Save abdivasiyev/1d653dd1d80a827f56f9de8c50557bda to your computer and use it in GitHub Desktop.

Select an option

Save abdivasiyev/1d653dd1d80a827f56f9de8c50557bda to your computer and use it in GitHub Desktop.
Go generic event dispatcher and event bus
package main
import (
"context"
"fmt"
)
type Event any
type Handler[E Event] interface {
Handle(context.Context, E) error
}
type HandlerFunc[E Event] func(context.Context, E) error
func (hf HandlerFunc[E]) Handle(ctx context.Context, event E) error {
return hf(ctx, event)
}
type EventBus[E Event] struct {
dispatcher Dispatcher
handlers []Handler[E]
}
func NewEventBus[E Event](d Dispatcher) *EventBus[E] {
return &EventBus[E]{dispatcher: d}
}
func (eb *EventBus[E]) Subscribe(h ...Handler[E]) *EventBus[E] {
eb.handlers = append(eb.handlers, h...)
return eb
}
func (eb *EventBus[E]) Dispatch(ctx context.Context, event E) error {
return eb.dispatcher.Dispatch(ctx, Emit(eb, event))
}
func (eb *EventBus[E]) emit(ctx context.Context, event E) error {
for _, h := range eb.handlers {
if err := h.Handle(ctx, event); err != nil {
return fmt.Errorf("event bus handle: %w", err)
}
}
return nil
}
type Emission func(context.Context) error
func Emit[E Event](bus *EventBus[E], event E) func(context.Context) error {
return func(ctx context.Context) error {
return bus.emit(ctx, event)
}
}
type Dispatcher interface {
Dispatch(context.Context, ...Emission) error
}
type dispatcher struct {
}
func NewDispatcher() Dispatcher {
return &dispatcher{}
}
func (d *dispatcher) Dispatch(ctx context.Context, emissions ...Emission) error {
for _, emit := range emissions {
if err := emit(ctx); err != nil {
return fmt.Errorf("failed to emit emission: %w", err)
}
}
return nil
}
type ExampleEvent struct{}
type exampleHandler struct{}
func (exampleHandler) Handle(context.Context, ExampleEvent) error {
fmt.Println("example event dispatched")
return nil
}
func main() {
d := NewDispatcher()
exampleBus := NewEventBus[ExampleEvent](d).Subscribe(
&exampleHandler{},
HandlerFunc[ExampleEvent](func(ctx context.Context, e ExampleEvent) error {
fmt.Println("HandlerFunc")
return nil
}),
)
d.Dispatch(context.Background(), Emit(exampleBus, ExampleEvent{}))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment