mattn/go-pubsub - GitHub使い方は簡単で、まず subscribe 側はある型を引数に持つコールバックで Sub を呼び出す。
https://github.com/mattn/go-pubsub
ps := pubsub.New()
ps.Sub(func(i int) {
fmt.Println("int subscriber: ", i)
})
そして publish 側はある型を指定して Pub を呼び出す。
ps.Pub(1)
Pub された値と同じ型の引数を持つ subscriber のみがメッセージを受け取れるという仕組み。構造体も渡せるので複雑なメッセージ内容もOK。ちなみに unsubscribe は Sub に渡したコールバック関数を Leave に渡すか、コールバック内で
ps.Sub(func(f *foo) {
fmt.Println("foo subscriber: ", f.bar)
ps.Leave(nil)
})
この様に nil を与えると呼出中のコールバックが unsubscribe されます。
簡単に chat を作ってみました。
package main
import (
"bufio"
"github.com/mattn/go-pubsub"
"log"
"net"
"strings"
)
func main() {
ps := pubsub.New()
l, err := net.Listen("tcp", ":5555")
if err != nil {
log.Fatal(err)
}
log.Println("Listing", l.Addr().String())
log.Println("Clients can connect to this server like follow:")
log.Println(" $ telnet server:5555")
for {
c, err := l.Accept()
if err != nil {
log.Fatal(err)
}
go func(c net.Conn) {
buf := bufio.NewReader(c)
ps.Sub(func(t string) {
log.Println(t)
c.Write([]byte(t + "\n"))
})
log.Println("Subscribed", c.RemoteAddr().String())
for {
b, _, err := buf.ReadLine()
if err != nil {
log.Println("Closed", c.RemoteAddr().String())
break
}
ps.Pub(strings.TrimSpace(string(b)))
}
ps.Leave(nil)
}(c)
}
}
やばい。簡単すぎる。