Using Matchers
Learn how to use matchers to filter and route events to the appropriate handlers. Matchers provide powerful filtering capabilities that allow subscribers to receive only the events they're interested in.
What You'll Learn
- The different types of matchers available
- How to match events by type
- How to match multiple event types with a single matcher
- How to match all events
- How matchers work with subscribers
Prerequisites
- Go 1.25+ installed
- Completed the Quick Start guide
- Understand basic publish/subscribe (see Basic Pub/Sub)
- Familiar with the Matcher concept
The Matcher Interface
All matchers implement the event.Matcher interface:
The Match method receives an event and returns true if the event matches the matcher's criteria.
Built-in Matchers
The library provides several built-in matchers for common use cases.
Is: Match a Specific Event Type
The Is matcher matches events of a specific type:
sub.On(event.Is("user.created"), func(e event.Event) {
// This callback is only invoked for events of type "user.created"
if payload, ok := e.Payload().(UserCreatedPayload); ok {
fmt.Printf("User created: %s\n", payload.Username)
}
})
This is the most commonly used matcher for simple event filtering.
IsOneOf: Match Multiple Event Types
The IsOneOf matcher matches any of the specified event types:
sub.On(event.IsOneOf("user.created", "user.updated", "user.deleted"), func(e event.Event) {
// This callback is invoked for any of the three user event types
switch payload := e.Payload().(type) {
case UserCreatedPayload:
fmt.Println("User was created")
case UserUpdatedPayload:
fmt.Println("User was updated")
case UserDeletedPayload:
fmt.Println("User was deleted")
}
})
This is useful when you want to handle multiple related event types with the same logic.
IsAny: Match All Events
The IsAny matcher matches all events:
sub.On(event.IsAny(), func(e event.Event) {
// This callback is invoked for every event published to the bus
fmt.Printf("Event of type %s received\n", e.Type())
})
Use this sparingly, as it will receive all events. It's most useful for logging, monitoring, or debugging.
IsFollowupOf: Match Followup Events
The IsFollowupOf matcher matches events that are followups of specific parent events:
sub.On(event.IsFollowupOf(parentEvent), func(e event.Event) {
// This callback is invoked for events that are followups of parentEvent
fmt.Println("Received a followup event")
})
This is useful for tracking specific chains of events.
Complete Example
See the complete, runnable example:
📁 examples/using-matchers/main.go
To run it:
Expected output:
[IsAny] Event received: user.created
[Is] User created: alice (alice@example.com)
[IsAny] Event received: user.updated
[IsOneOf] User updated: alice.smith (alice.smith@example.com)
[IsAny] Event received: user.deleted
[IsOneOf] User deleted: user-002
[IsAny] Event received: system.health_check
Matcher demonstration complete!
Notice how:
- The Is("user.created") matcher only receives the user creation event
- The IsOneOf("user.updated", "user.deleted") matcher receives both update and delete events
- The IsAny() matcher receives all events
Custom Matchers
You can create custom matchers by implementing the Matcher interface:
type HighPriorityMatcher struct{}
func (m HighPriorityMatcher) Match(e event.Event) bool {
// Implement your custom matching logic
if payload, ok := e.Payload().(MyPayload); ok {
return payload.Priority == "high"
}
return false
}
// Use the custom matcher
sub.On(HighPriorityMatcher{}, func(e event.Event) {
fmt.Println("High priority event received")
})
Custom matchers are useful when you need matching logic that's not covered by the built-in matchers.
Matcher Composition
While you can't directly compose matchers with logical operators, you can achieve similar results by:
- Using
IsOneOffor OR logic (match any of multiple types) - Creating custom matchers for AND logic (all conditions must be true)
- Using multiple
On()calls for different matchers
Best Practices
- Be specific: Use the most specific matcher possible to avoid unnecessary event processing
- Group related types: Use
IsOneOffor event types that share common handling logic - Avoid IsAny: Only use
IsAnywhen truly necessary (logging, debugging, monitoring) - Type assertions: Always check the payload type before accessing it in your callback
- Error handling: Handle type assertion failures gracefully
Key Concepts Used
- Matcher: A filter for events (see Concepts)
- Subscriber: Receives and processes events (see Concepts)
- Event: The fundamental unit of information (see Concepts)
- Type: Categorizes events (see Concepts)
Next Steps
- Basic Publish/Subscribe - Review the fundamentals
- Event Chaining - Learn how to create sequences of related events
- Using Carriers - Dispatch multiple events as a unit