Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

ファイルの埋め込みをstatikからgo:embedに置き換えた

サーバーサイドエンジニアの田実です!

Yappliではメールテンプレートや多言語化の設定ファイルをGoに埋め込んで使うためにstatikを使っていました。Go 1.16から導入されたgo:embedによってビルド時にファイルコンテンツを埋め込めるようになったので、statikからgo:embedに置き換えてみました!*1

置き換え前(statik)

対象のディレクトリ内のファイルをstatik.goに変換します。

# `go get github.com/rakyll/statik` でstatikを予めインストール
# (1.17以降は `go install github.com/rakyll/statik@latest`)
$ statik -src=srcPath

その後、変換したstatik.goのパッケージと github.com/rakyll/statik/fs をimportして変換したファイルコンテンツを読み込みます。

import (
    "github.com/rakyll/statik/fs"
    _ "github.com/xxx/yyy/statik"
)

func main() {
    statikFS, err := fs.New()
    if err != nil {
        // error handling
    }
    f, err := statikFS.Open("/path/to/file") // `-src` のパスをルートとする絶対パス指定
    if err != nil {
        // error handling
    }
    buf, err := ioutil.ReadAll(f)
    // ...
}

置き換え後(go:embed)

import "embed"

//go:embed srcPath/*
var fs embed.FS

func main() {
    f, err := fs.Open("path/to/file") // embedを指定したファイルからの相対パス指定
    if err != nil {
        // error handling
    }
    buf, err := ioutil.ReadAll(f)
    // ...
}

コード自体はそこまでスッキリしていないのですが、ビルド時にstatikコマンドを事前に実行しなくて良くなったのでビルドスクリプト・Makefileがスマートになりました…w

実コードでは埋め込みファイルの fs 変数は別パッケージに切り出して他のパッケージから読み込めるようにしています。 また、Openのファイル名指定がstatikは絶対パスで / が先頭に付きますが、go:embedは相対パスなので / を取り除いてファイル名を指定する必要があります。

まとめ

statikからgo:embedに置き換える方法について紹介しました。 statikのバージョン管理やインストールなどの前準備はハマりポイントだったので、Go本体だけで埋め込みファイルを運用できるのは便利ですね…!

*1:Goのバージョンは積極的にアップグレードしております!そろそろ1.17になる予定…!