handlename's blog

コード片など

flycheck用のgo-vetコマンドを再定義する

わけあってgoamzのコードをemacs上で読んでいたら、 こことかで flycheck経由のgo-vetが次のようなワーニングを出していた。

composite literal uses unkeyed fields

AttributeDefinitionsはsliceだから、なんでunkeyed fieldsと書かれているのかがわからない。 スルーしてもいいのだけど、気になるのでググったら 「-composites=falseするといいよ!」ってあった。 https://code.google.com/p/go/issues/detail?id=6820

というわけでflycheckのcheckerを再定義した。

(flycheck-define-checker go-vet
  "A go syntax checker."
  :command ("go" "tool" "vet" "-composites=false" source-inplace)
  :error-patterns ((error line-start
                          (file-name) ":" line ":" (minimal-match (message))
                          line-end))
  :modes (go-mode))

これで上記のワーニングは出なくなった。

goでJSONを比較したい場合

JSONでデータをやりとりするパッケージで、 得られるJSONが期待するものかどうかをテストするときにどうすればいいのか、という話。

ググってもこれといったものが見つけられなかったので interface{}な変数にjson.Unmarshalしてからreflect.DeepEqualしてみたら うまく動いていそうな感じだったのでここに記す。

実際に使う場合はどのキーの値が間違ってる、とか このキーが余計、とかがわかったほうが親切なんだけど、 それをやるとなるとreflect.DeepEqualじゃなくて 自分で再帰して比較する処理を書かないといけなそう。

http://play.golang.org/p/x_TtCRnHjv

以下はplaygroundと同じコードと出力。

続きを読む

mimic っていう http mock サーバーを書いた

  • go 1.3.1

引き続き go 勉強中。 mux というものを知ったので これを使ってなにか書いてみた結果。

https://github.com/handlename/mimic

ユースケース

フロントエンドの人と平行して作業をするときに、

「このAPIまだ出来てないの?」
「とりあえず持っくでいいからレスポンス用意してよ」

と言われることがよくある。

そういう場合はとりあえず固定のレスポンスを返すコントローラーを定義して、 開発サーバーに上げたりするのだけど、まあめんどくさい。

なんとかフロントの人で完結できないか?

コードを書かずに動かせるモックサーバーがあれば・・・!

(あとづけです)

最初に書いたとおり mux を使ってみようっていうのがモチベーションなので、 同じことができるツールが有るかとかはぜんぜん調べてない。

これはなに?

JSON で設定を書くとその通りにレスポンスを返してくれる http mock サーバー。

こういう JSON を書いて、

{
    "rules": [
        {
            "method"  : "GET",
            "path"    : "/",
            "content" : "hello"
        }
    ]
}

mimic に食わせると、

$ mimic --config=config.json

こういうレスポンスを返してくれる。

$ curl http://localhost:3390/
hello%

詳しくは README 参照。

なにがうれしいか

今後の展望

  • config.sample.json にしれっと書いてあるけどコード中では使ってない content-type 対応
  • 長めのレスポンスとか JSON とか(いちいちエスケープしないといけない) は設定ファイル中には書きにくいので、 別ファイルを参照できるように

余談

YAPC::Asia 2014 参加中の隙間時間で書いた。 ちょうど聞いてた @deeet さんのトーク がすごいタイムリーでためになった。

get-git-ignore というツールを書いた

  • go 1.3.1

なにか書き始めるとき、小さいものでもとりあえず git で管理するようにしている。 で、ちょっと大きくなると .gitignore ファイルを置く必要が出てくる。

このときいつも github/gitignore から 該当言語を探して raw の URL をたどってダウンロード、というのをやっていたのだけど、 いいかんげんめんどくさくなってきたので楽して取ってこれるツールを書いた。 go の練習も兼ねてる。

REAMEにあるように言語一覧のファイルを用意して設定を .zshrc に書くと、 こんな風にこんな風にインタラクティブに絞り込んで目的の言語の .gitignore を取ってくることができる。 peco 便利。

f:id:handlename:20140819211429g:plain

言語一覧ファイルの生成機能くらいはつけてもいいかなーと思ったりしてる。 言語一覧ファイルは不要になった。追記参照。

追記 2014-08-21

mattn さんに プルリク を頂いて、 .gitignore.list を用意する必要がなくなりました。

しれっとコマンド中のエラー処理とか、net/http のレスポンスの処理とかも 直してもらっててありがたや〜

追記 2014-08-22

ブコメで知りましたが、

などの便利ツール・サービスが有るようです。 便利な世の中だ。

go-opts というパッケージを書いた

  • go 1.3.1

go 言語でコマンドライン引数を受け取る場合、 flag というモジュールを使う。

こんなコードを書くと --xxx / -xxx 形式でコマンドライン引数を受け取ることができる。

package main

import (
    "flag"
    "fmt"
)

func main() {
    var hoge int
    flag.IntVar(&hoge, "hoge", 10, "hoge value")
    flag.Parse()

    fmt.Printf("hoge = %d\n", hoge)
}
$ go run sample_flag.go --hoge=1
hoge = 1

$ go run sample_flag.go
hoge = 10

引数の種類が増えると煩雑になるし、管理も面倒だなーと思ったので、 楽ちんに書けるパッケージを書いてみた。

こんなふうに書ける。

package main

import (
    "fmt"
    "github.com/handlename/go-opts"
)

type myOpts struct {
    Hoge int `flag:"hoge" default:"10" description:"hoge value"`
}

func main() {
    o := myOpts{}
    opts.Parse(&o)
    fmt.Printf("hoge = %d\n", o.Hoge)
}

あ、あれ、コード長くなってる?? ま、まあ引数が多くなった時に定義と保存先をまとめて宣言できると便利なんじゃないかな・・・。

いまのところ自分が必要になった型しか実装してないので、 stringintfloat64bool しか受け取れない。 あと、テストがない。 flag パッケージのテストを読んでみよう。