😸

【Go】statik を使用してビルド時に静的ファイルをバイナリに含める

2020/12/17に公開

statik とは

Go は通常、ビルド時にソースファイル以外の静的ファイルをバイナリに含めることはできません。
そのため、もしも設定ファイル等の静的ファイルが必要な Go アプリケーションを配布する場合、バイナリとは別にそれらの静的ファイルも一緒に配布する必要があり、非常に手間です。
そういった場合に statik を使用すると静的ファイルも一緒にバイナリに含めることができるため、単一のバイナリを配布するだけで済むようになります。

GitHub: rakyll/statik: Embed files into a Go executable

使い方

今回検証するディレクトリ構造は以下です。
static_files/ ディレクトリ以下の静的ファイルをバイナリに含めます。

$ tree
.
└── static_files
    └── hoge.txt

準備

go getstatik をインストールします。

$ go get github.com/rakyll/statik

インストールが完了したら statik コマンドを実行します。
-src オプションに静的ファイルを含むディレクトリパスを指定します。

$ statik -src=./static_files

すると、 statik/statik.go というファイルが生成されます。

$ tree
.
├── static_files
│   └── hoge.txt
└── statik
    └── statik.go

statik/statik.go の中身は以下のようになっています。
先頭のコメントに DO NOT EDIT. とあるように、このファイルは編集しないようにしましょう

statik/statik.go
// Code generated by statik. DO NOT EDIT.

package statik

import (
	"github.com/rakyll/statik/fs"
)

func init() {
	data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\xfd]\x90Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00	\x00hoge.txtUT\x05\x00\x01\xef\xf3\xd9_\xca\xc8OO\xe5\x02\x04\x00\x00\xff\xffPK\x07\x08\x9d\x87\xe2\xb9\x0b\x00\x00\x00\x05\x00\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xfd]\x90Q\x9d\x87\xe2\xb9\x0b\x00\x00\x00\x05\x00\x00\x00\x08\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00hoge.txtUT\x05\x00\x01\xef\xf3\xd9_PK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00?\x00\x00\x00J\x00\x00\x00\x00\x00"
	fs.Register(data)
}

実際に statik を使用して静的ファイルを読み込んでみる

こんな感じ。

main.go
package main

import (
	"bytes"
	"fmt"

	_ "./statik" // NOTE: go module を使用している場合は絶対パスを指定する必要があります
	"github.com/rakyll/statik/fs"
)

func main() {
	// statkFS は `http.FileSystem` 型
	statikFS, err := fs.New()
	if err != nil {
		panic(err)
	}

	// file は `http.File` 型
	file, err := statikFS.Open("/hoge.txt")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// ファイルを読み込んで出力
	buf := new(bytes.Buffer)
	buf.ReadFrom(file)
	fmt.Println("ファイルの内容:", buf.String())
}

ビルドして実行してみます。

# ビルド
$ go build -o statik-example

# 確認のため静的ファイルは削除する
$ rm -rf static_files

# ファイルの内容が出力された!
$ ./statik-example
ファイルの内容: hoge

非常に簡単且つ便利ですね。

参考

https://github.com/rakyll/statik

Discussion