تنفيذ مستمعي الأحداث في الانتقال عبر القنوات

يهدف هذا المنشور إلى شرح كيفية تنفيذ مستمع حدث باستخدام قنوات Go ، ما يمكن للمرء أن يطلق عليه مراقب في شروط نمط التصميم.

المشكلة

لدي كلب ينبح أحيانًا ، وعندما يحدث هذا عادةً ما أخبره ألا ينبح. وككل الكلاب ، يتغوط أحيانًا لذا أحتاج إلى التقاطه.

سأصمم كلبي على أنه هيكل يحتوي على قائمة من مستمعي الأحداث ، وهي قائمة بالأشخاص الذين يعتنون به.

سيبعث الكلب الأحداث لهؤلاء المستمعين عندما يحدث شيء ما.

إليك كيفية تصميم كلبنا في Go: لدينا هيكل يحمل اسمًا وقائمة من القائمين على رعايته ، و 3 أحداث: يمكننا إضافة جليسة كلاب جديدة ، ويمكننا إزالة واحدة ، ويمكن لكلبنا إصدار أحداث.

// Dog has a name and a list of people caring for him and watching
// what he does
type Dog struct {
    name    string
    sitters map[string][]chan string
}

// AddSitter adds an event listener to the Dog struct instance func (b *Dog) AddSitter(e string, ch chan string) { if b.sitters == nil { b.sitters = make(map[string][]chan string) } if _, ok := b.sitters[e]; ok { b.sitters[e] = append(b.sitters[e], ch) } else { b.sitters[e] = []chan string{ch} } }

// RemoveSitter removes an event listener from the Dog struct instance func (b *Dog) RemoveSitter(e string, ch chan string) { if _, ok := b.sitters[e]; ok { for i := range b.sitters[e] { if b.sitters[e][i] == ch { b.sitters[e] = append(b.sitters[e][:i], b.sitters[e][i+1:]) break } } } }

// Emit emits an event on the Dog struct instance func (b *Dog) Emit(e string, response string) { if , ok := b.sitters[e]; ok { for , handler := range b.sitters[e] { go func(handler chan string) { handler <- response }(handler) } } }

نركض كلبنا

لنأخذ الكلب إلى العالم ونرى كيف يعمل. أولاً ، أنا الوحيد الذي يعتني بالكلب ، لذا سأضيف نفسي كجليسة للكلبbalto.AddSitter()لجميع الأحداث التي يمكنني التعامل معها:barkوpoopوhungry.

بعد فترة سئمت من التقاط البراز واستأجرت مربي كلاب للتجول والقيام بالمهمة نيابة عني ، لكنني ما زلت أتحمل أمر إخبار الكلب بعدم النباح وإطعامه.

package main

import ( “fmt” “time” )

func main() { balto := Dog{“Balto”, nil}

<span style="color:#a6e22e">flavio</span> <span style="color:#f92672">:=</span> make(<span style="color:#66d9ef">chan</span> <span style="color:#66d9ef">string</span>)

<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">AddSitter</span>(<span style="color:#e6db74">"bark"</span>, <span style="color:#a6e22e">flavio</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">AddSitter</span>(<span style="color:#e6db74">"poop"</span>, <span style="color:#a6e22e">flavio</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">AddSitter</span>(<span style="color:#e6db74">"hungry"</span>, <span style="color:#a6e22e">flavio</span>)

<span style="color:#66d9ef">go</span> <span style="color:#66d9ef">func</span>() {
    <span style="color:#66d9ef">for</span> {
        <span style="color:#a6e22e">msg</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&lt;-</span><span style="color:#a6e22e">flavio</span>
        <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Flavio: "</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">msg</span>)
    }
}()

<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"The dog barked!"</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">Emit</span>(<span style="color:#e6db74">"bark"</span>, <span style="color:#e6db74">"Told not to bark!"</span>)

<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"The dog pooped!"</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">Emit</span>(<span style="color:#e6db74">"poop"</span>, <span style="color:#e6db74">"Picked up poop!"</span>)

<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"The dog is hungry!"</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">Emit</span>(<span style="color:#e6db74">"hungry"</span>, <span style="color:#e6db74">"Feed the dog!"</span>)

<span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Sleep</span>(<span style="color:#ae81ff">3</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>)

<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">"\n.\n.\n.\n"</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">RemoveSitter</span>(<span style="color:#e6db74">"poop"</span>, <span style="color:#a6e22e">flavio</span>)

<span style="color:#75715e">// Hired a dog sitter to pick up poop

dogsitter := make(chan string) balto.AddSitter(“poop”, dogsitter) fmt.Println(“Flavio hired a dogsitter to pick up poop, won’t pick it up again”)

<span style="color:#66d9ef">go</span> <span style="color:#66d9ef">func</span>() {
    <span style="color:#66d9ef">for</span> {
        <span style="color:#a6e22e">msg</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&lt;-</span><span style="color:#a6e22e">dogsitter</span>
        <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Dogsitter: "</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">msg</span>)
    }
}()

<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Dog barked!"</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">Emit</span>(<span style="color:#e6db74">"bark"</span>, <span style="color:#e6db74">"Told not to bark!"</span>)

<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Dog has pooped!"</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">Emit</span>(<span style="color:#e6db74">"poop"</span>, <span style="color:#e6db74">"Picked up poop!"</span>)
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Dog has pooped again!"</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">Emit</span>(<span style="color:#e6db74">"poop"</span>, <span style="color:#e6db74">"Picked up poop, again!"</span>)
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"The dog is hungry!"</span>)
<span style="color:#a6e22e">balto</span>.<span style="color:#a6e22e">Emit</span>(<span style="color:#e6db74">"hungry"</span>, <span style="color:#e6db74">"Feed the dog!"</span>)

<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Scanln</span>()

}

أنا استخدمfmt.Scanln()في النهاية لمنع البرنامج من الخروج عندmain()انتهى ، في حين لا يزال ينتظر حتى يكتمل goroutines التعامل مع الأحداث.

إذا قمت بتشغيله ، فيبدو أن موظفنا الجديد يقوم بالعمل الذي نتوقعه أيضًا ، ويمكننا الاسترخاء:

$ go run eventlistener.go
The dog barked!
The dog pooped!
The dog is hungry!
Flavio: Picked up poop!
Flavio: Told not to bark!
Flavio: Feed the dog!

. . . Flavio hired a dogsitter to pick up poop, wont pick it up again Dog barked! Dog has pooped! Dog has pooped again! The dog is hungry! Flavio: Told not to bark! Dogsitter: Picked up poop! Dogsitter: Picked up poop, again! Flavio: Feed the dog!


المزيد من دروس Go: