生涯未熟

生涯未熟

プログラミングをちょこちょこと。

goroutine使ってゴニョゴニョするCLIツールを作った時の備忘録

備忘録として自分用に書きます。

cobra良いよ

以前までurfave/cli使ってたんですが、「dockerのcliとかcobra使ってたよな〜」とよくcobra見かけるようになったので使ってみた。

$ cobra initでアプリケーションの土台作ってくれるので、煩わしいこと考えずにサクッと開発に入れて良い。

あとは、urfave/cliよりも細かく挙動の管理が出来そう(未検証)。

またエラー時などにカスタマイズした標準出力する場合は、SilenceUsageSilenceErrorsをやっといたら吉。

きちんとデザインパターン使ってみた

結城浩さんのデザパタ本を読み終わったので早速デザパタを取り入れてみた。

Goの場合、こちらのリポジトリに実装例がまとまってるので読むと得るものが多い。

github.com

雑にgoroutine回した時の注意

雑に大量のスレッド作成した時にpanic等で落ちると、大量のログが吐かれて元のエラー内容が確認できない場合があるので、

$ go run main.go 2>hoge.txt

とかでファイルに吐いてあげると良い。

複数のgoroutineから同一mapを参照すると死

エラーで死。1.6からエラー吐いてくれるようになったらしい。

排他制御やるか、channelとWaitGroup使って後からまとめてmapに代入したりするべし。

プログレスバー

CLIツールでプログレスバーを実装する場合、cheggaaa/pbが簡単。

見た目が気に入らない場合はbriandowns/spinnerとか使うと良い。

今回はhttp.Get()でのダウンロードの際にpbを使ってみたが、大量のgoroutineで並列処理した状態でプログレスバーを出すと表示が50%で止まったりしたので、並列度を定義し徐々に表示を増やしていった方が良い感じ。

ちなみにhttp.Get()プログレスバーを出す場合はこんな感じのコード。

 response, err := http.Get(url)
    if err != nil {
            // エラー処理
    }

    fileSize := response.ContentLength
    progressBar := pb.New64(fileSize).SetUnits(pb.U_BYTES)
    progressBar.Start()
    reader := progressBar.NewProxyReader(response.Body)

    defer response.Body.Close()

    io.Copy(file, reader)

Goglandの謎挙動

開発途中でpbをgopkgからインストールし、Goglandで使おうとしたら該当ディレクトリを読み込まず。

再起動したら読み込んだが、もしかしたら読み込みタイミングがアレなのかもしれない。

[追記] 上部メニューバーのFile→Synchronizeの実行でファイルの再読込を行えばOK