EventBus — Go event bus library

EventBus — lightweight event bus for Go with async support and cross-process events. Used in siyuan, evcc, guppy, shinkro. 2k+ stars, 1k+ dependents. MIT.

Lightweight event bus for Go — subscribe/publish with sync and async handlers, optional cross-process events via RPC. MIT-licensed, widely used in note-taking, EV charging, and event-driven Go projects.

→ GitHub · → Documentation (pkg.go.dev)

GitHub Stars Dependent repos Dependent packages Forks
2k+ 1k+ 833+ 241

Used by SiYuan, EVCC, Guppy, Shinkro, Argo CD ecosystem and others. See the list below.


Projects and Companies Using EventBus

A list of notable open-source projects and products that depend on github.com/asaskevich/EventBus.

📊 Overview Statistics

  • Total Dependent Repositories: 1k+
  • Total Dependent Packages: 833+
  • GitHub Stars: 2k+
  • Forks: 241

🏢 Notable Dependents

# Project Description Repository
1 SiYuan Local-first note-taking and knowledge management siyuan and community forks
2 EVCC Electric vehicle charging controller ownctrl-energy/evcc
3 Guppy Game server / tooling storacha/guppy
4 HarmonyLite HarmonyOS-related tooling wongfei2009/harmonylite
5 Shinkro Media / automation shinkro/shinkro
6 Props Configuration / props management tietang/props
7 Trendyol go-dcp-bq Data pipeline (DCP to BigQuery) Trendyol/go-dcp-bq
8 Argo CD Operator GitOps operator ecosystem argocd-operator and forks
9 Hollowtrees Event-driven tooling kompute/hollowtrees
10 MCPSpy MCP / tooling internauticos/MCPSpy

API Overview

Core Methods

Method Description
New() Returns a new EventBus with empty handlers.
Subscribe(topic, fn) Subscribe to a topic. Returns error if fn is not a function.
SubscribeOnce(topic, fn) Subscribe once; handler is removed after first execution.
Unsubscribe(topic, fn) Remove callback for a topic.
HasCallback(topic) Returns true if any callback is subscribed to the topic.
Publish(topic, args…) Execute callbacks for the topic; extra args are passed to the callback.
SubscribeAsync(topic, fn, transactional) Async callback; transactional controls serial vs concurrent execution.
SubscribeOnceAsync(topic, fn) One-time async subscription.
WaitAsync() Wait for all async callbacks to complete.

Cross-Process Events

EventBus can work over the network with two RPC services:

  • Server — listens for remote subscriptions and publishes events to clients.
  • Client — subscribes to topics on a remote server and receives events locally.

Files: server.go, client.go, network_bus.go. See code examples below.


Code Examples

Example 1: Basic Subscribe and Publish

package main

import (
	"fmt"
	"github.com/asaskevich/EventBus"
)

func calculator(a int, b int) {
	fmt.Printf("%d\n", a+b)
}

func main() {
	bus := EventBus.New()
	bus.Subscribe("main:calculator", calculator)
	bus.Publish("main:calculator", 20, 40)
	bus.Unsubscribe("main:calculator", calculator)
}

Example 2: Async Subscription

package main

import (
	"fmt"
	"time"
	"github.com/asaskevich/EventBus"
)

func slowCalculator(a, b int) {
	time.Sleep(3 * time.Second)
	fmt.Printf("%d\n", a+b)
}

func main() {
	bus := EventBus.New()
	bus.SubscribeAsync("main:slow_calculator", slowCalculator, false)
	bus.Publish("main:slow_calculator", 20, 60)
	fmt.Println("start: do some stuff while waiting for a result")
	fmt.Println("end: do some stuff while waiting for a result")
	bus.WaitAsync()
	fmt.Println("do some stuff after waiting for result")
}

Example 3: SubscribeOnce

func HelloWorld() { fmt.Println("Hello, World!") }
// ...
bus.SubscribeOnce("topic:handler", HelloWorld)
bus.Publish("topic:handler") // HelloWorld runs once, then is removed

Example 4: Server (Cross-Process)

func main() {
	server := NewServer(":2010", "/_server_bus_", New())
	server.Start()
	// ...
	server.EventBus().Publish("main:calculator", 4, 6)
	// ...
	server.Stop()
}

Example 5: Client (Cross-Process)

func main() {
	client := NewClient(":2015", "/_client_bus_", New())
	client.Start()
	client.Subscribe("main:calculator", calculator, ":2010", "/_server_bus_")
	// ...
	client.Stop()
}

Use Cases

  1. In-Process Event-Driven Design — decouple components with topics (e.g. UI ↔ logic, plugins).
  2. Async Handlers — run subscribers in goroutines; use WaitAsync() when you need to wait.
  3. One-Shot HandlersSubscribeOnce / SubscribeOnceAsync for single-use reactions.
  4. Cross-Process Events — Server/Client RPC for distributing events across processes or machines.

Resources

Resource Link
GitHub github.com/asaskevich/EventBus
Go docs pkg.go.dev/github.com/asaskevich/eventbus
Dependents GitHub dependency graph

EventBus — lightweight event bus for Go with async and cross-process support. Open source, MIT.

© Aliaksei Saskevich