2013年11月3日日曜日

Golang Cafe #2を開催しました。

先週に引き続き、Golang Cafe #2を開催しました。
今回は、encoding/jsonパッケージのMarshal()から読み始めました。

それまでに、前回のExampleの事を復習していたら、godocコマンドのハックに…。
(ですが、本題と違ったのでまた違う日にやることにしました)

色々出てきたのでメモ。
引数の型がinterface{}になる時は、「何でもOK」という意味。(他の言語で言う、Object、object、void *、variant…など。)

deferキーワード。呼び出した関数が終了した後に呼び出される、後処理用スタックに積む。(その場で処理は実行されないので、ファイルのクローズなどをまとめておくと良い。)

recover()はdeferキーワードを使って呼び出した関数内でしか利用できないので注意。

reflect.Valueは、今日は読まないが、「ポインタを持った構造体」
reflect.ValueOf()はポインタを持った構造体を返す関数ということにしておく。

読んだ所は、encoding/json#Marshalを掘り下げる感じで。

  1. encoding/json#Marshal
  2. e = &encodeState{}
  3. e.marshal()
    1. エラーチェック用defer関数を登録して、e.reflectValue()
    2. reflectValueQuoted(v, false)で呼び出す。(1.1.2だと267行目付近)
      1. IsValid()かどうかをチェック
      2. Marshalerインターフェイスを実装しているかどうかをチェック(TypeAssertionを使って、変換する)
      3. Marshalerインターフェイスではない場合、ポインタをもらっているという想定で、v.Addr().Interface().(Marshaler)で参照先の値を取り出してTypeAssertionする。
        1. TypeAssertionは変換できない場合もあるので、代入用変数と、チェック用の変数を2つ左辺に記述する形で使う。(i, ok := v.(int)…など)チェック用変数がfalseの場合は変換できなかった事を示す。(interfaceを実装していない、型が違うなど。)
        2. MarshalJSON()([]byte, error)を実装していれば、自分で実装したJSONエンコード処理が呼ばれる。
      4. それ以外は、reflect.Kind()で型の種類を取得して、それぞれの方法で出力する。
        1. 構造体はフィールドごとに再起呼び出し。
        2. fallthroughキーワードは次のcaseを実行する。
          1. Goのswitchはデフォルトbreak!
        3. reflect.Kind()はhttp://goo.gl/uDQOPOのconst値を返してくる。
        4. invalid、unsafePointer、channel、func、Mapのキーがstring以外のものは、変換できずerrorを返す。

それから、私が作成したサンプルコードとテストコードをまとめてgithubに置きました。
https://github.com/tyokoyama/golangcafe
次からはこのリポジトリにまとめてCommitしていくことにします。
(忘れてなかったら、各回ごとにbranchも作っておくようにします。)

次回は、goroutine & channels関連をやってみる予定です。