fizzbuzz(6), with 'knock-service'
package main import ( "flag" "fmt" "net/http" "strconv" "sync" ) var ( vol = flag.Int("v", 100, "volume") max = flag.Int("m", 10000, "send numbers") ) type msg struct { Q int A int } type comm struct { Sch chan msg Rch chan msg } type reply struct { Comm chan *comm } var ( poolSub chan reply = make(chan reply) poolAdd chan *comm = make(chan *comm) ) var ( standbyPub chan reply = make(chan reply) standbyOk chan *comm = make(chan *comm) ) func save() { var ( pool []*comm = make([]*comm, 0, *vol) standby []*comm = make([]*comm, 0, *vol) ) for { select { case x := <-poolSub: last := len(pool) - 1 if last > 0 { x.Comm <- pool[last] pool = pool[:last] } else { x.Comm <- nil } case x := <-poolAdd: standby = append(standby, x) case y := <-standbyPub: last := len(standby) - 1 if last > 0 { y.Comm <- standby[last] standby = standby[:last] } else { y.Comm <- nil } case y := <-standbyOk: pool = append(pool, y) } } } func set() func(func(msg) msg) { var comms []comm for i := 0; i < *vol; i++ { comms = append(comms, comm{}) comms[i].Sch = make(chan msg) comms[i].Rch = make(chan msg) } return func(g func(x msg) msg) { for i := 0; i < *vol; i++ { i := i rch := comms[i].Sch sch := comms[i].Rch poolAdd <- &comms[i] go func() { for { x := <-rch sch <- g(x) poolAdd <- &comms[i] } }() } } } const ( FIZZBUZZ = iota FIZZ BUZZ NOTFIZZBUZZ ) func init() { flag.Parse() go save() f := set() g := func(m msg) msg { x := m.Q switch { case x%15 == 0: m.A = FIZZBUZZ case x%3 == 0: m.A = FIZZ case x%5 == 0: m.A = BUZZ default: m.A = NOTFIZZBUZZ } return m } f(g) } var ctrl chan struct{} = make(chan struct{}) func let() { close(ctrl) } func send(g func() msg) { for i := 0; i < *max; i++ { go func() { res := make(chan *comm) <-ctrl for { poolSub <- reply{res} c := <-res if c != nil { c.Sch <- g() break } } close(res) }() } } // done is for waiting all-received-timing var done chan struct{} = make(chan struct{}) func wait() { <-done } func recv(f func(chan msg) error) { var wg sync.WaitGroup wg.Add(*max) go func() { for { res := make(chan *comm) standbyPub <- reply{res} c := <-res if c != nil { go func() { f(c.Rch) wg.Done() }() standbyOk <- c } close(res) } }() wg.Wait() close(done) } func main() { // "Knock-service" // GET http://localhost:8080/knock?k=n // then n'th fizzbuzz execute. f := func() func() msg { var n int knock := make(chan struct{}) http.HandleFunc("/knock", func(w http.ResponseWriter, r *http.Request) { k := r.URL.Query().Get("k") if rep, err := strconv.Atoi(k); err == nil { for ; rep > 0; rep-- { knock <- struct{}{} } } else { knock <- struct{}{} } fmt.Fprint(w, http.StatusOK) }) go http.ListenAndServe(":8080", nil) return func() msg { <-knock n++ return msg{Q: n} } } // send and g sends numbers to setted goroutines g := f() go send(g) // recv and h processes the results from setted goroutines h := func(ch chan msg) error { m := <-ch var ans string switch m.A { case FIZZBUZZ: ans = "fizzbuzz" case FIZZ: ans = "fizz" case BUZZ: ans = "buzz" case NOTFIZZBUZZ: ans = "-" } fmt.Println(m.Q, ":", ans) return nil } go recv(h) let() // start wait() // wait }
fizzbuzz(6)
package main import ( "flag" "fmt" "sync" ) var ( vol = flag.Int("v", 100, "volume") max = flag.Int("m", 10000, "send numbers") ) type msg struct { Q int A int } type comm struct { Sch chan msg Rch chan msg } type reply struct { Ch chan *comm } var ( poolSub chan reply = make(chan reply) poolAdd chan *comm = make(chan *comm) ) var ( standbyPub chan reply = make(chan reply) standbyOk chan *comm = make(chan *comm) ) func save() { var pool []*comm = make([]*comm, 0, *vol) var standby []*comm = make([]*comm, 0, *vol) for { select { case x := <-poolSub: last := len(pool) - 1 if last > 0 { x.Ch <- pool[last] pool = pool[:last] } else { x.Ch <- nil } case x := <-poolAdd: standby = append(standby, x) case y := <-standbyPub: last := len(standby) - 1 if last > 0 { y.Ch <- standby[last] standby = standby[:last] } else { y.Ch <- nil } case y := <-standbyOk: pool = append(pool, y) } } } func set() func(func(msg) msg) { var comms []comm return func(g func(x msg) msg) { for i := 0; i < *vol; i++ { comms = append(comms, comm{}) comms[i].Sch = make(chan msg) comms[i].Rch = make(chan msg) } for i := 0; i < *vol; i++ { i := i rch := comms[i].Sch sch := comms[i].Rch poolAdd <- &comms[i] go func() { for { x := <-rch sch <- g(x) poolAdd <- &comms[i] } }() } } } const ( FIZZBUZZ = iota FIZZ BUZZ NOTFIZZBUZZ ) func init() { flag.Parse() go save() f := set() g := func(m msg) msg { x := m.Q switch { case x%15 == 0: m.A = FIZZBUZZ case x%3 == 0: m.A = FIZZ case x%5 == 0: m.A = BUZZ default: m.A = NOTFIZZBUZZ } return m } f(g) } var ctrl chan struct{} = make(chan struct{}) func let() { close(ctrl) } func send(g func() msg) { for i := 0; i < *max; i++ { go func() { res := make(chan *comm) <-ctrl for { poolSub <- reply{res} c := <-res if c != nil { c.Sch <- g() break } } close(res) }() } } // done is for waiting all-received-timing var done chan struct{} = make(chan struct{}) func wait() { <-done } func recv(f func(chan msg) error) { var wg sync.WaitGroup wg.Add(*max) go func() { for { res := make(chan *comm) standbyPub <- reply{res} c := <-res if c != nil { go func() { f(c.Rch) wg.Done() }() standbyOk <- c } close(res) } }() wg.Wait() close(done) } func main() { // send and g sends numbers to setted goroutines f := func() func() msg { var n int return func() msg { n++ return msg{Q: n} } } g := f() go send(g) // recv and h processes the results from setted goroutines h := func(ch chan msg) error { m := <-ch var ans string switch m.A { case FIZZBUZZ: ans = "fizzbuzz" case FIZZ: ans = "fizz" case BUZZ: ans = "buzz" case NOTFIZZBUZZ: ans = "-" } fmt.Println(m.Q, ":", ans) return nil } go recv(h) let() // start wait() // wait }
memo
-fno-stack-protector
mecabのbuild
repository がgithubに移行。 ipadic をconfigureする時に、--with-mecab-config="xxx"が必要。
$ git clone https://github.com:taku910/mecab.git $ cd mecab/mecab $ ./configure --with-charset=utf8 --enable-utf8-only $ make $ make check $ sudo make install $ cd ../.. $ wget http://sourceforge.net/projects/mecab/files/mecab-ipadic/2.7.0-20070801/mecab-ipadic-2.7.0-20070801.tar.gz $ tar zxvf mecab-ipadic-2.7.0-20070801.tar.gz $ cd mecab-ipadic-2.7.0-20070801 $ which mecab-config /usr/local/bin/mecab-config $ ./configure --with-mecab-config=/usr/local/bin/mecab-config --with-charset=utf8 $ make $ sudo make install
import ( "io" "os/exec" ) func mecabCmd(w io.Writer, r io.Reader, dic string) error { cmd := exec.Command("mecab", "-d", dic) cmd.Stdin = r cmd.Stdout = w err := cmd.Run() if err != nil { return err } return nil }
Goのloop
loopのvariable
for _, v := range items { v := v go func(){ process(v) }() }
for _, v := range items { go func(v type) { process(v) }(v) }
loopとwait group
var wg sync.WaitGroup for _, v := range items { v := v wg.Add(1) go func(){ process(v) wg.Done() }() } wg.Wait()
loopとwaitgroupとchannel
var wg sync.WaitGroup ch := make(chan type) for _, v := range items { wg.Add(1) go func(v type) { defer wg.Done() res, _ := process(v) ch <- res }(v) } go func(){ wg.Wait() close(ch) }() for res := range { process(res) }
loopとwaitgroupとchannel、semaphore
var wg sync.WaitGroup ch := make(chan type) sem := make(chan struct{}, num) for _, v := range items { wg.Add(1) go func(v type) { defer wg.Done() sem <- struct{}{} res, _ := process(v) <-sem ch <- res }(v) } go func(){ wg.Wait() close(ch) }() for res := range { process(res) }