Keep on moving

あんまりまとまってないことを書きますよ

aferoを使ってGoでのファイル生成のUnitTestを書きやすくする

Go言語の永遠の初心者です。 自分用の便利スクリプトを用意するときにシェルスクリプトではなくGoを使うときのTIpsです。 Goでファイル生成するときによく使っているライブラリを紹介します。

TL;DR

  • aferoを使うことでファイル生成のUnitTestが書きやすくなる

背景

Goでスクリプトを書いていてある程度処理をしてからファイルを生成することがあると思います。 ただスクリプトでの条件が増えてきたりするとそこからUnitTestsが書きたくなることがあると思います。 osライブラリを使うとファイルが作れるのですが... テストのタイミングでは現物のファイルを作るのではなく、 メモリ上でファイルを展開できるといいなーと思うことが多いですよね。

今回紹介するライブラリ

背景 のところで説明した話はこのライブラリを使うと行うことができます。 github.com

install

$ go get github.com/spf13/afero

使い方の例

import "github.com/spf13/afero"


// os packagと同じように扱える
AppFs := afero.NewOsFs()
MakeEmptyFile(AppFs, fileName)

func MakeEmptyFile(fs afero.Fs, s string) {
    dirName := filepath.Dir(s)
    exists, err := afero.DirExists(fs, dirName)
    if !exists && err != nil {
        mkdirErr := fs.MkdirAll(dirName, os.ModePerm)
        if err != nil {
            log.Fatal(mkdirErr)
        }
    }
    emptyFile, err := fs.Create(s)
    if err != nil {
        log.Fatal(err)
    }
    emptyFile.Close()
}

テストの例

func TestMakeEmptyFile(t *testing.T) {

        // テスト用にメモリ上でFSのmockを扱う
    AppFs := afero.NewMemMapFs()
    fileName := "./test.py"

        // メモリ上で扱ってくれるのでファイル本体ができることはない.
    MakeEmptyFile(AppFs, fileName)

        // でもUnitTestは実行可能
    // file exists
    exists, _ := afero.Exists(AppFs, fileName)
    assert(t, exists, true)

    // file is empty
    bytes, _ := afero.ReadFile(AppFs, fileName)
    assert(t, string(bytes), "")

}

func assert(t *testing.T, actual, expected interface{}) {
    if actual != expected {
        t.Errorf("got: %v\nwant: %v", actual, expected)
    }
}

まとめ

osパッケージと同じ使い方ができるのでaferoに切り替えるのは非常に簡単です。 つまりやめたくなったら元に戻すのも簡単です。 UnitTestsもやりやすくなるのでぜひ皆様も使ってみてください。

回文かどうかを判定する関数を実装して、いろいろ速度計測してみた

回文かどうかを判定する関数を書きたくなりまして、goで実装してみました。
回文 - Wikipedia


さくっとかけてしまったのでなんパターンか書いてみて一番早い書き方を探ってみました。
近頃仕事でJVM言語を書く機会が多いので、久々に違う言語でかくと楽しいもんですよねー

実装案

以下の4実装で比較してみました

  1. reverseして元の文字列と比較
  2. 文字列を最初/最後 => 2番目/後ろから2番目 => ...で比較
  3. ↑をutf8モジュールを使って実装
  4. ↑をutf8モジュール+rangeで回す実装

結果

というわけでutf8モジュール+rangeで回す実装が一番早いみたいです。
もっと良い実装を思いついた方がいましたら、ぜひ教えてください。