SoFunction
Updated on 2025-03-04

Simple implementation of event manager based on Go language

In programming, event managers are a common tool for triggering actions through notifications. In Go language, we can implement event processing by creating event managers and listeners. This article will introduce the implementation of a simple Go event manager and improve its performance through asynchronous improvements.

Listener

First, we need to create a listener. In this implementation, the listener is just a function that receives event parameters.

type Listener[T any] func(T)

Event Manager

Event Manager is a structure used to manage events and listeners. It has two methods:AddandRunAddMethod is used to attach a new listener to an event, andRunMethods are used to execute event managers.

type Manager[T any] interface {
	Add(n string, l Listener[T])
	Run()
}

Abstract Event Manager

For ease of use, we can create an abstract event manager that implements part of the general logic of the event manager interface. Although Go is not object-oriented, we can achieve similar effects through simulation.

type BaseManager[T any] struct {
	lst map[string][]Listener[T]
}

func (m *BaseManager[T]) Invoke(n string, args T) {
	for _, ls := range [n] {
		ls(args)
	}
}

func (m *BaseManager[T]) Add(n string, l Listener[T]) {
	[n] = append([n], l)
}

BaseManagerProvidedAddMethods are used to add listeners andInvokeMethod is used to trigger the listener for the specified event.

Specific event manager

The following is an example implementation of a specific event manager: Command Event Manager. The manager receives commands entered by the user from the console and triggers the corresponding event according to the command type.

type Command struct {
	Kind string
	Args []string
}

type CommandEventManager struct {
	BaseManager[*Command]
}

func (m *CommandEventManager) Run() {
	var (
		inp  string
		args Command
	)

	(&inp)

	cmd := (inp, ":")

	if l := len(cmd); l == 0 {
		("no-command", nil)
	} else if l > 1 {
		 = (cmd[1], " ")
	}

	 = cmd[0]

	("any-command", &args)
	(, &args)
}

func NewCommandEventManager() Manager[*Command] {
	return &CommandEventManager{
		BaseManager: BaseManager[*Command]{lst: make(map[string][]Listener[*Command])},
	}
}

RunMethods obtain commands entered by the user from the console and parse command parameters. If there are no commands or command parameters, the "no-command" event is triggered; otherwise, the "any-command" event and specific command events are triggered.

Add a listener

Let's add some listeners to the command event manager.

func main() {
	cem := NewCommandEventManager()

	("no-command", func(_ *Command) {
		("no command was recieved")
	})

	("any-command", func(c *Command) {
		("the %s command was executed", )
	})

	("sum", func(c *Command) {
		a, _ := ([0])
		b, _ := ([1])
		("the sum result is: %d", a+b)
	})

	()
}

In the example above, the program is executed only once, but you can put it in an infinite loop to continuously listen for commands.

Asynchronous improvements

The execution of the event manager can be changed to asynchronously to improve performance. Each time an event is executed, it can be used as agoroutinePerform processing. Even the execution of each listener can be placed in onegoroutineto improve concurrency performance.

Through the above improvements, we can better utilize the concurrency characteristics of Go language and improve event processing efficiency.

This is the end of this article about simply implementing event manager based on Go. For more related go event manager content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!