LoginSignup
9
1

More than 5 years have passed since last update.

goroutineを用いてGetWild

Last updated at Posted at 2016-12-20

こちらはGetWild AdventCalenderの22日目の記事です。

はじめに

ネタが...思い浮かばない...
image

しかし、書かねばなりません。

そうだgoにはgoroutineがあった

そこで私は思い出しました。普段使っているgoにはgoroutineがあることを。
これを使えば私もいつでも気軽にWildを得る事ができるはずです。

早速実装します

今回はgoroutineを用いて標準出力に"G" "e" "t" "W" "i" "l" "d" の
7文字からランダムに1文字抽出し、"GetWild"になったタイミングに何かが起こる事にします。

package main

import (
    "fmt"
    "math/rand"
    "time"
)

var (
    getWildWords = []string{"G", "e", "t", "W", "i", "l", "d"}
)

func main() {
    c := make(chan string)
    w := ""

    for {
        go getWildAndTough(c)
        w += <-c
        if len(w) == len(getWildWords) {
            fmt.Println(w)
            w = ""
        }
    }
}

func getWildAndTough(c chan string) {
    rand.Seed(time.Now().UnixNano())
    c <- getWildWords[rand.Intn(len(getWildWords))]
}

これでgoroutineを使用して、チャンネル経由で7文字の文字列を受け取る事が出来るようになりました。
しかし、これは if len(r) == len(getWildWords) { あたりがかっこ悪いので7本のワーカーでそれぞれ1文字づつ返却するようにします。

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

var (
    getWildWords = []string{"G", "e", "t", "W", "i", "l", "d"}
)

func main() {
    wg := &sync.WaitGroup{}
    c := make(chan string)

    for {
        r := ""
        for i := 0; i < 7; i++ {
            wg.Add(1)
            go getWildAndTough(wg, c)
            r += <-c
        }
        wg.Wait()
        fmt.Println(r)
        r = ""
    }
    close(c)
}

func getWildAndTough(wg *sync.WaitGroup, c chan string) {
    defer wg.Done()
    rand.Seed(time.Now().UnixNano())
    c <- getWildWords[rand.Intn(len(getWildWords))]
}

syncパッケージを利用し、それぞれのgoroutineが処理を終えるまで待ち文字を出力するようにしました。駅の掲示板にXYZと書いて待っている時の心で書きます。

package main

import (
    "fmt"
    "math/rand"
    "os/exec"
    "sync"
    "time"
)

var (
    getWildWords = []string{"G", "e", "t", "W", "i", "l", "d"}
    g            string
)

const (
    textGetWild = `
  ____      _    __        ___ _     _
 / ___| ___| |_  \ \      / (_) | __| |
| |  _ / _ \ __|  \ \ /\ / /| | |/ _  |
| |_| |  __/ |_    \ V  V / | | | (_| |
 \____|\___|\__|    \_/\_/  |_|_|\__,_|
`
)

func init() {
    for _, v := range getWildWords {
        g += v
    }
}

func main() {
    wg := &sync.WaitGroup{}
    c := make(chan string)

    for {
        w := ""
        for i := 0; i < 7; i++ {
            wg.Add(1)
            go getWildAndTough(wg, c)
            w += <-c
        }
        wg.Wait()
        if isGetWild(w) {
            fmt.Println(textGetWild)
            exec.Command("say", "-v", "Ava", w).Run()
            break
        }
        w = ""
    }
    close(c)
}

func getWildAndTough(wg *sync.WaitGroup, c chan string) {
    defer wg.Done()
    rand.Seed(time.Now().UnixNano())
    c <- getWildWords[rand.Intn(len(getWildWords))]
}

func isGetWild(w string) bool {
    if g == w {
        return true
    }
    return false
}

上記のようにすれば下記のようにGetWildとAAを出力させつつ
槇村香のように「Get Wild」と喋ります。

  ____      _    __        ___ _     _
 / ___| ___| |_  \ \      / (_) | __| |
| |  _ / _ \ __|  \ \ /\ / /| | |/ _  |
| |_| |  __/ |_    \ V  V / | | | (_| |
 \____|\___|\__|    \_/\_/  |_|_|\__,_|

皆様、2016年も残り短くなりましたが2017年もタイヤを切りつける勢いで
GetWildしていきましょう。くれぐれもWildなコードは書きませんように。

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1