avatarAvi Kotzer

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

5070

Abstract

do that:</p><div id="2e8b"><pre>eventHandler<span class="hljs-selector-class">.Handle</span>(event1, <span class="hljs-built_in">ExampleMiddlewareFoo</span>(<span class="hljs-built_in">ExampleMiddlewareBar</span>(handle)))</pre></div><h1 id="a8a5">Managing Events with Handlers and Middleware</h1><p id="f869">Most articles I read explain how to use this design pattern; this one deals with implementing the internal logic. So let's start coding.</p><p id="35c4">The full code for this article can be found <a href="https://github.com/xNok/slack-go-demo-socketmode/blob/main/examples/middleware/main.go">here</a> to help you follow along.</p><h2 id="0f88">Designing events</h2><p id="b622">First, we are going to enumerate the list of events that our system can handle. The way we create enumeration in Go is a bit different than in other programming languages. In Go, we are going to use a set of constants sharing the same <code>type</code>. Here I define a type <code>EventType</code>that represents a string with the event's name.</p><div id="b181"><pre>// <span class="hljs-keyword">type</span> <span class="hljs-type">used </span>to enumerate events <span class="hljs-keyword">type</span> <span class="hljs-type">EventType </span>string</pre></div><div id="4817"><pre>const ( event1 EventType <span class="hljs-operator">=</span> <span class="hljs-string">"event1"</span> event2 EventType <span class="hljs-operator">=</span> <span class="hljs-string">"event2"</span> )</pre></div><p id="e041">Next, we define the event itself. In our example, the<code>Event</code> as a type which can be selected among the list of <code>EventType</code> created above.</p><div id="2bc9"><pre><span class="hljs-keyword">type</span> <span class="hljs-type">Event</span> struct { <span class="hljs-type">Type</span> <span class="hljs-type">EventType</span> <span class="hljs-type">Data</span> interface{} }</pre></div><h2 id="df6c">Create an event sender (for test purpose)</h2><p id="60aa">To test our system, we will need to create a small function to send events every 2s. Each<code>Event</code> is transmitted via a <a href="https://tour.golang.org/concurrency/2">channel</a> and, the <code>eventSender</code> below sends a random <code>Event</code> of type <code>event1</code> or <code>event2</code> to a channel.</p><blockquote id="53f3"><p><i>Channels are a type which you can send and receive values, they are great for communication among goroutines. In other words, there are perfect for sending and receive event through your application.</i></p></blockquote><div id="ffd1"><pre><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">eventSender</span><span class="hljs-params">(c <span class="hljs-keyword">chan</span> EventType)</span></span> {</pre></div><div id="7f57"><pre> for { // Send <span class="hljs-selector-tag">a</span> random event <span class="hljs-selector-tag">to</span> the channel rand<span class="hljs-selector-class">.Seed</span>(<span class="hljs-selector-tag">time</span><span class="hljs-selector-class">.Now</span>()<span class="hljs-selector-class">.Unix</span>()) events := []EventType{ event1, event2, } n := rand.<span class="hljs-built_in">Int</span>() % <span class="hljs-built_in">len</span>(events)</pre></div><div id="6101"><pre> c <- events[n] <span class="hljs-comment">// send event to channel</span></pre></div><div id="5285"><pre> // <span class="hljs-keyword">wait</span> a <span class="hljs-built_in">bit</span> <span class="hljs-built_in">time</span>.Sleep(<span class="hljs-number">2</span> * <span class="hljs-built_in">time</span>.Second) } }</pre></div><h2 id="000c">Handler and dispatcher</h2><p id="e562">We first need a struct to hold the list of events we want to listen to and which function to call whenever that event is transmitted. This struct also contains the channel used for communicating events.</p><div id="280d"><pre><span class="hljs-comment">// Create a struct to hold config</span> <span class="hljs-comment">// And simplify dependency injections</span> <span class="hljs-keyword">type</span> EventHandler <span class="hljs-keyword">struct</span> { <span class="hljs-comment">// Event channel</span> Events <span class="hljs-keyword">chan</span> Event <span class="hljs-comment">// hold the registedred event functionss</span> EventMap <span class="hljs-keyword">map</span>[EventType][]<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(Event)</span></span> }</pre></div><p id="aa6c">Next, we need to provide an initializing constructor for our <code>EventHandler</code>.</p><div id="a4ed"><pre><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NewEventHandler</span><span class="hljs-params">()</span></span> *EventHandler { eventMap := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[EventType][]<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(Event)</span></span>) event

Options

s := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> Event)</pre></div><div id="78bb"><pre> return <span class="hljs-variable">&</span>EventHandler<span class="hljs-punctuation">{</span> <span class="hljs-symbol"> Events:</span> events, <span class="hljs-symbol"> EventMap:</span> eventMap, <span class="hljs-punctuation">}</span> <span class="hljs-punctuation">}</span></pre></div><p id="98fe">Then, we can create our <code>Handle</code> function that associates the event with a callback function.</p><div id="308c"><pre><span class="hljs-comment">// register the handler function to handle an event type</span> func (h *EventHandler) <span class="hljs-built_in">Handle</span>(e EventType, f <span class="hljs-built_in">func</span>(Event)) { h<span class="hljs-selector-class">.EventMap</span><span class="hljs-selector-attr">[e]</span> = <span class="hljs-built_in">append</span>(h<span class="hljs-selector-class">.EventMap</span><span class="hljs-selector-attr">[e]</span>, f) }</pre></div><p id="e42a">Finally, we create the <code>EventDispatcher</code> function, the core of this mechanism. The <code>EventDispatcher</code>process any event sent to a channel, check its type, and if any function has been registering for that type, we call all registered functions.</p><div id="6597"><pre><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *EventHandler)</span></span> EventDispatcher() { <span class="hljs-keyword">for</span> evt := <span class="hljs-keyword">range</span> h.Events { log.Printf(<span class="hljs-string">"event recieved: %v"</span>, evt) <span class="hljs-keyword">if</span> handlers, ok := h.EventMap[evt.Type]; ok { <span class="hljs-comment">// If we registered an event</span> <span class="hljs-keyword">for</span> _, f := <span class="hljs-keyword">range</span> handlers { <span class="hljs-comment">// exacute function as goroutine</span> <span class="hljs-keyword">go</span> f(evt) } } } }</pre></div><h1 id="13e4">Using our system</h1><p id="4d4e">Everything is ready; we can start using our event handling system.</p><ol><li>Instantiate our event Handler</li><li>Register which event to listen to and what function to callback</li><li>Start the event sender</li><li>Start the event dispatcher</li></ol><div id="62ab"><pre><span class="hljs-keyword">func</span> <span class="hljs-title function_">main</span><span class="hljs-params">()</span> {</pre></div><div id="5b09"><pre> <span class="hljs-variable">eventHandler</span> := <span class="hljs-function"><span class="hljs-title">NewEventHandler</span>()</span></pre></div><div id="d244"><pre> eventHandler.Handle(event1, <span class="hljs-keyword">func</span><span class="hljs-params">()</span> { <span class="hljs-built_in">log</span>.Printf(<span class="hljs-string">"event Handled: %v"</span>, event1) })</pre></div><div id="5c56"><pre> <span class="hljs-variable">go</span> <span class="hljs-function"><span class="hljs-title">eventSender</span>(<span class="hljs-variable">eventHandler.Events</span>)</span></pre></div><div id="30f2"><pre> eventHandler<span class="hljs-selector-class">.EventDispatcher</span>()</pre></div><div id="9bf2"><pre>}</pre></div><p id="e590">The result should be along those lines:</p><figure id="5ee7"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*_D-GCRSu3K8CgTBXewJjJQ.gif"><figcaption></figcaption></figure><p id="19d6">Since we only handle an event of type <code>event1</code>, only <code>event1</code> shows as <code>Hansled</code>. All is good!</p><p id="d48a">The full code for this article can be found <a href="https://github.com/xNok/slack-go-demo-socketmode/blob/main/examples/middleware/main.go">here</a>.</p><h1 id="6f5e">Interesting Articles tackling the same topic</h1><ul><li><a href="https://drstearns.github.io/tutorials/gomiddleware/">Middleware Patterns in Go</a></li><li><a href="https://sathishvj.medium.com/web-handlers-and-middleware-in-golang-2706c2ecfb75">Web Handlers and Middleware in GoLang</a></li><li><a href="https://readmedium.com/lightweight-event-management-implemented-by-go-a654d59ac65">Lightweight event management implemented by Go</a></li><li><a href="https://readmedium.com/the-7-most-important-software-design-patterns-d60e546afb0e">The 7 Most Important Software Design Patterns</a></li></ul><p id="13e7"><i>Do you want <b>unlimited access</b> to all my content and many other writers’ content on Medium? Consider using my affiliate link to <a href="https://couedeloalexandre.medium.com/membership">become a Medium member today</a></i></p><h2 id="853a">Further reads</h2> <figure id="81d2"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://couedeloalexandre.medium.com/embed/list/3f9d03f2cb8f" allowfullscreen="" frameborder="0" height="184" width="undefined"> </div> </div> </figure></iframe></div></div></figure></article></body>

Grugru

This palm tree is not doubly despicable

Photo by Nika Benedictova on Unsplash

Today’s New York Times Spelling Bee letters:

Art: Iva Reztok

G, I, M, N, P, U, and center R (all words must include R)

Merriam-Webster says…

Credit: merriam-webster.com

Silly little dictionary! Don’t you know that grugru can’t possibly be a word if The New York Times says it ain’t?

For a complete list of rejected words, check out the Spelling Bee Master.

What’s your favorite dord* from today’s puzzle?

My Two Cents

I must be one of the few people in the world who hasn’t seen any of the movies in the Despicable Me franchise. I know it’s risky admitting such an awful thing, and that it could get me labeled a pariah… or worse, a Gru.

There are currently five films (Despicable Me, Despicable Me 2, Despicable Me 3 Minions, and Minions: The Rise of Gru), with a sixth one, Despicable Me 4, expected to be released in 2024. I know who Gru and the Minions are, and I have nothing against these movies or Illumination studios. I just haven’t had the time to sit down and go through them. (As an aside, in Spanish-speaking countries the Despicable Me title was translated as Mi villano favorito, which means “my favorite villain”.)

Want to know something even more terrible? I still haven’t caught up on all the Toy Story movies. Yeah, I can already see the number of my followers rapidly decreasing as Medium readers seek to distance themselves from me.

I had no idea what to expect when I looked up the word grugru in the dictionary. Maybe a bird, figuring the name came from its call. Turns our there is a slight connection between what I was thinking and the second definition in the dictionary. Read on to find out!

The tree

Our friends at Merriam-Webster tell us grugru was borrowed from the American Spanish word of Cariban origin, akin to Yao grugru, which literally meant a basket made from the tree palms.

The tree grows to a height of between 50 and 65 feet (about 15–20 meters), while its leaves can reach lengths of 10 to 14 feet (3–4 meters).

One of the most impressive things about this palm is its trunk, which is covered in long spines that make it practically impossible to climb… unless you’re one of the kids in Honey, I Shrunk the Kids.

Photo by Hardyplants

Here is a closeup:

Otherwise, this tree looks pretty much like any other palm. Its fruit ripens to yellow and the pulp is sticky and slimy, but tough to reach. The hard outer shell protects an even harder inner shell surrounding a dry white filling that tastes of coconut. Which could be a reason the fruit is known as the coco Paraguayo (Paraguayan coconut) in some countries of southern South America.

In Mexico, the sap from the local palm species (Acrocomia mexicana) is used to make a fermented alcoholic beverage known as coyol wine. Rumor has it the inebriation effect of this wine is caused not by the alcohol itself, but by a reaction triggered when a person is exposed to the hot sun after having imbibed. Which means that if you drink it at night, instead of getting a hangover the next day, you’ll get drunk!

The worm

According to Merriam-Webster, the grugru grub, or worm, is the larva of a tropical weevil in the Rhyncophorus genus. It seems as though they committed a typo. This genus is spelled with an “h” after the “c”: Rhynchophorus. I’ll have to alert them about the typo, as it caused me to lose all of ten seconds during my research. Sometimes Google’s autofill does come in handy…

It seems logical to think that the name of the grub comes from its association with the palm tree. However, I did find one source that claims the grugru bug is called that in South America “because it makes a clicking noise while feeding”. The online Britannica does mention “a clucking sound” made by the larvae of Rhynchophorus cruentatus “while boring in cabbage palms”, but falls short of saying it has anything to do with its name.

The above-mentioned species of Rhynchophorus, or palm weevil, is found mostly in Florida, where it is considered a serious pest. The species native to the Americas is Rhynchophorus palmarum, or the South American palm weevil

Photo by Didier Descouens

…whose grubs have been consumed as a source of protein for millennia by indigenous populations:

Photo by Uli von Oben

I’m guessing skewering them like this also sends the message “do not mess with my palm trees” quite effectively.

Some of the palm weevils are actually quite pretty or interesting-looking, like the palmetto weevil (Rhynchophorus cruentatus)…

Photo by Matt edmonds

…or the red palm weevil:

Photo by Didier Descouens

The larvae of most of the ten known species of Rhynchophorus are eaten. It may have to do with their relatively large size and easy availability. I’ve never tried them, so I can’t comment about their taste.

The Association of African Universities has a video that explains the efforts made by the Kwame Nkrumah University of Science and Technology in Ghana to farm the larvae of palm weevils, known there as the akokono. (If you’re a vegetarian or vegan, you may not want to watch.)

Now you know. Next time you’re in Mexico and you want to try some coyol wine, ask the locals where you can go milk a grugru palm. People will think you’re crazy, of course. Not because you want to milk a tree… but because the editors of the Spelling Bee decided that grugru is a dord*.

You can check out my previous entry on another dord* here:

*What the heck is a dord, you ask? Here’s the answer:

Spelling Bee
Language
Food
Trees
Culture
Recommended from ReadMedium