akms道東

ITイベント,勉強会への参加記録や趣味のことが書いてあるブログです.

WordCount実装でGolang入門

久しぶりの更新は技術ネタです。

Golangはじめました

ちょうど勉強会でGolangの話を聴いて興味がわいたので触ってみた。
まずA Tour of Goというブラウザだけで学習できるチュートリアルから始めてみた。
その中で41ページ目(この表現であってるか微妙だが)にある、WordCount関数の実装問題がGolangの実装の入門にちょうど良いなと思った。

WordCount関数
func WordCount(s string) map[string]int {
    return map[string]int{"x": 1}
}

これがWordCount関数の初期状態。引数は文字列1つ。
キーが文字列で要素が数値のmapが返り値となっている。

とりあえず実装

下記はこの実装問題にたどり着くまでに行った演習と問題ページにあるヒントから単純に書いた回答。
これでも問題なく動作する。

func WordCount(s string) map[string]int {
    str := strings.Fields(s)
    m := make(map[string]int)
    for i := range str { 
      m[str[i]] += 1
    }
    return m
}

Golangでは『var hoge string = "fuga"』のように
var宣言、変数名、型、初期化子というように変数を宣言する。
また関数内では以下のように『:=』でvarの代わりに暗黙的な型宣言で代入ができる。
関数内だしvar宣言して書かなくていいならこっち使おうという安直な考えで記述。

str := strings.Fields(s)
m := make(map[string]int)

Golangでは繰り返し文はforのみ。
条件はwhileのような書き方もできる。また条件を指定しないと無限ループになる。
また今回のようにrangeを使うことで変数のインデックス分繰り返すといった処理ができる。
ここでも『:=』で代入。そしてループが終了するとmを返す。

for i := range str {
  m[str[i]] += 1
}
return m
リファクタリング

一度はこれで良いかと思ったが、動けば良いというものでは全く勉強にならない。
そこで改めて自分のコードを書き直してみた。

まず初めにword_mapというキーが文字列で要素が数値のmapを返すことを明示した。

func WordCount(s string) (word_map map[string]int) {

次に『:=』では『strings.Fields(s)』が何を返すのかリファレンスを見なければ確認できなかった。
そこで一目で分かるようにvar宣言、変数名、型、初期化子という形で記述した。

var str []string = strings.Fields(s)

rangeを使うと実は変数からインデックスと値の両方が返ってくる。
今回は処理的にインデックスは不要だった。
そこで『_』に代入することでインデックスを破棄し、値のみをループの中で使用した。
最後にreturnだけで終了してるが、前述の通りword_mapという
キーが文字列で要素が数値のmapを返すことを明示しているのでこの一行で終了することができる。

for _,key := range str {
   word_map[key] += 1
}
return 

以下はここまで説明したものを一つにまとめたものである。
一番最初に提示した回答例と違い、処理内容が初見でも理解しやすくなっていると思う。

func WordCount(s string) (word_map map[string]int) {
    var str []string = strings.Fields(s)
    word_map = make(map[string]int)
    for _,key := range str {
        word_map[key] += 1
    }
    return 
}

こうして一つ一つを理解していくなかでとくに『_』を使ったインデックスの破棄や、
最初に変数名と型を宣言しておくことで『return』と書くだけでその値が返ることなど面白いなと感じた。

今後の学習予定

とりあえずA Tour of Goを完了させる。
また今週末から来週にかけてGolangの勉強会に3回ほど参加する予定なのでとても楽しみだ。