rakyll/statik を使って Goでファイル系のリソースも一緒にビルドして配布しちゃう!

blog.hatappi.me

以前こんな記事を書いていた
ただgo-bindataはメンテされてなくてAwesome Goから削除されたり作者だった方がGithubのアカウント削除して他の方が同じ名前で作成してgo-bindataを作ったりと色々あった
ということで違うものを探していて次のにたどり着いた

github.com

作者の方はGoogleの方でheyという負荷試験ツールを作ったりしている方で安心して使用できるかなと思います

前回と同じく次のようなディレクトリ構造をもったプロジェクトがあるとする

.
├── files
│   └── sample.txt
└── main.go

sample.txtの中身は次のようになっている

sample!
sample!!
sample!!!

main.goの中身を次のようになっている

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    f, err := os.Open("files/sample.txt")
    if err != nil {
        panic(err)
    }
    scanner := bufio.NewScanner(f)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    f.Close()
}

ただこれだとbuildして実行する際に files/sample.txt が存在している必要がある
buildしてバイナリになったのを配布したいのにファイルがセットで必要になるのは面倒

ということで今回はrakyll/statikを使用してこれを解決する

インストール

$ go get github.com/rakyll/statik

実行

$ statik -src=files

実行が完了すると statik/statik.go というファイルが作成されている
後はこれをプログラム内から読み込むようにするとビルド時に一緒に入るので、先程のようにファイルを一緒に配布しなくてもよくなる

package main

import (
    "fmt"
    "io/ioutil"

    "github.com/rakyll/statik/fs"

    _ "./statik"
)

func main() {
    statikFS, err := fs.New()
    if err != nil {
        panic(err)
    }

    f, err := statikFS.Open("/sample.txt")
    if err != nil {
        panic(err)
    }

    b, err := ioutil.ReadAll(f)
    if err != nil {
        panic(err)
    }

    s := string(b)
    fmt.Print(s)
}