- Go 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
- Переписывание шины на generic-модель с маршрутизацией по типу события - Удаление trie-структуры, путей, wildcard и опций конструктора - Подписка возвращает типизированный канал Listener[E] - Отписка через контекст с закрытием канала слушателя - Non-blocking публикация с буфером в одно событие - Нулевое значение Bus готово к использованию без конструктора - Переход на Go 1.27 с использованием generic methods - Добавление тестов с проверкой конкурентности под race detector - Обновление README под новый API |
||
| .golangci.yml | ||
| bus.go | ||
| bus_test.go | ||
| go.mod | ||
| LICENSE | ||
| README.md | ||
eventbus - Асинхронная шина событий для Go
eventbus - это реализация асинхронной шины событий для языка программирования
Go. Библиотека предоставляет механизм публикации и подписки на типизированные
события: подписка выполняется по типу события, доставка осуществляется в
каналы подписчиков.
Особенности
- Типобезопасность: Подписка и доставка строго типизированы - слушатель
Listener[E]получает только события типаE - Любые типы событий: Событием может быть любой тип - структура, указатель,
строка, число; типы
Tи*T- это разные события - Zero-value ready: Шина не требует конструктора - нулевое значение
eventbus.Busготово к использованию - Асинхронная доставка: События доставляются в каналы подписчиков без блокировки издателя: если буфер слушателя (1 событие) заполнен, событие отбрасывается
- Отписка через контекст: При отмене контекста подписка удаляется, канал слушателя закрывается
- Потокобезопасность: Все операции синхронизированы с использованием
sync.RWMutex - Generic methods: Реализована с использованием generic-методов (Go 1.27+)
Установка
go get go.neonxp.ru/eventbus
Требуется Go 1.27 или новее.
Использование
package main
import (
"context"
"fmt"
"go.neonxp.ru/eventbus"
)
type UserLogin struct {
User string
}
type UserLogout struct {
User string
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
var bus eventbus.Bus
// Подписываемся на события по типу
logins := bus.Subscribe[UserLogin](ctx)
logouts := bus.Subscribe[UserLogout](ctx)
go func() {
for ev := range logins {
fmt.Printf("User login: %s\n", ev.User)
}
}()
go func() {
for ev := range logouts {
fmt.Printf("User logout: %s\n", ev.User)
}
}()
// Публикуем события - тип события определяется автоматически
bus.Publish(UserLogin{User: "user123"})
bus.Publish(UserLogout{User: "user123"})
}
Отписка выполняется отменой контекста подписки - канал слушателя закроется:
ctx, cancel := context.WithCancel(context.Background())
ch := bus.Subscribe[UserLogin](ctx)
// ...
cancel()
for range ch {} // канал закроется, цикл завершится
API
func (b *Bus) Subscribe[E any](ctx context.Context) Listener[E]
Подписывается на события типа E. Возвращает канал-слушатель для получения
событий. При отмене контекста подписка удаляется, а канал закрывается.
func (b *Bus) Publish(ev any)
Отправляет событие всем подписчикам, подписанным на тип события. Доставка не блокирует издателя: если буфер слушателя заполнен (не прочитано предыдущее событие), событие отбрасывается.
type Listener[E any] chan E
Типизированный канал слушателя.
Нюансы
- Типы
Tи*T- это разные события: подписчикSubscribe[T]не получитPublish(&value{})и наоборот - Буфер слушателя - 1 событие. Если подписчик не успевает читать, новые события отбрасываются. Для гарантированной доставки увеличивайте скорость чтения или используйте собственную буферизацию
Publish(nil)безопасен: событие не доставляется никому
Лицензия
Этот проект лицензирован в соответствии с GNU General Public License версии 3 (GPLv3). Подробности смотрите в файле LICENSE.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2026 Alexander NeonXP Kiryukhin <i@neonxp.ru>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Ссылки
- Репозиторий: https://gitrepo.ru/NeonXP/eventbus.git
- Автор: Alexander NeonXP Kiryukhin i@neonxp.ru
English Version
eventbus is an implementation of an asynchronous event bus for the Go
programming language. The library provides a publish-subscribe mechanism for
typed events: subscriptions are made by event type, and events are delivered
to the subscribers' channels.
Features
- Type safety: Subscribing and delivery are strictly typed - a
Listener[E]receives only events of typeE - Any event types: Any type can be an event - struct, pointer, string,
number; types
Tand*Tare different events - Zero-value ready: The bus does not require a constructor - the zero
value of
eventbus.Busis ready to use - Asynchronous delivery: Events are delivered to the subscribers' channels without blocking the publisher: if a listener's buffer (1 event) is full, the event is dropped
- Unsubscribe via context: When the context is canceled, the subscription is removed and the listener channel is closed
- Thread-safe: All operations are synchronized using
sync.RWMutex - Generic methods: Implemented using generic methods (Go 1.27+)
Installation
go get go.neonxp.ru/eventbus
Requires Go 1.27 or newer.
Usage
package main
import (
"context"
"fmt"
"go.neonxp.ru/eventbus"
)
type UserLogin struct {
User string
}
type UserLogout struct {
User string
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
var bus eventbus.Bus
// Subscribe to events by type
logins := bus.Subscribe[UserLogin](ctx)
logouts := bus.Subscribe[UserLogout](ctx)
go func() {
for ev := range logins {
fmt.Printf("User login: %s\n", ev.User)
}
}()
go func() {
for ev := range logouts {
fmt.Printf("User logout: %s\n", ev.User)
}
}()
// Publish events - the event type is inferred automatically
bus.Publish(UserLogin{User: "user123"})
bus.Publish(UserLogout{User: "user123"})
}
Unsubscribe by canceling the subscription context - the listener channel will be closed:
ctx, cancel := context.WithCancel(context.Background())
ch := bus.Subscribe[UserLogin](ctx)
// ...
cancel()
for range ch {} // the channel will be closed, the loop will end
API
func (b *Bus) Subscribe[E any](ctx context.Context) Listener[E]
Subscribes to events of type E. Returns a listener channel for receiving
events. When the context is canceled, the subscription is removed and the
channel is closed.
func (b *Bus) Publish(ev any)
Publishes an event to all subscribers of the event type. Delivery does not block the publisher: if a listener's buffer is full (the previous event has not been read), the event is dropped.
type Listener[E any] chan E
A typed listener channel.
Caveats
- Types
Tand*Tare different events: aSubscribe[T]subscriber will not receivePublish(&value{})and vice versa - The listener buffer is 1 event. If a subscriber does not keep up with reading, new events are dropped. For guaranteed delivery, read faster or use your own buffering
Publish(nil)is safe: no one receives the event
License
This project is licensed under the GNU General Public License version 3 (GPLv3). See the LICENSE file for details.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2026 Alexander NeonXP Kiryukhin <i@neonxp.ru>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Links
- Repository: https://gitrepo.ru/NeonXP/eventbus.git
- Author: Alexander NeonXP Kiryukhin i@neonxp.ru