概要
Go 1.16 から追加となった embed
パッケージについてのメモ4個目。
前回は以下。
embed
パッケージのドキュメントは以下。
今回は、複数のファイルを埋め込んで、その内容を embed.FS
で取得するサンプルです。
embed.FS
は、こちらも Go1.16 で追加された io/fs
の 各インターフェースを embed 側で実装しているものです。
embed.FS
は、以下のインターフェースを実装しています。
- fs.ReadDirFS
- fs.ReadFileFS
なので、ファイルとディレクトリの両方を扱えるってことですね。
embedパッケージで、複数のファイルを一つの変数で埋め込んで利用する場合は、embed.FS
を利用する必要があります。
埋め込みたい変数に、必要なだけ //go:embed xxxx
を書けば埋め込まれます。
例えば以下のようにします。
//go:embed data //go:embed helloworld.txt var content embed.FS
上記では、data
というディレクトリと helloworld.txt
というファイルを埋め込むよう指示しています。
サンプル
以下のサンプルでは、同一ディレクトリに配置されている helloworld.txt
と data
ディレクトリを埋め込んで利用しています。
helloworld.txt というファイルは以下の内容です。
hello world
data
ディレクトリの中は以下な感じ。
$ tree data data ├── dotnet.txt ├── golang.txt ├── go.txt └── python.txt 0 directories, 4 files
それぞれのファイルの中身は言語の名前が一行で入っているだけです。
んで、利用する側は以下のような感じ。
package embeds import ( "embed" "fmt" "github.com/devlights/gomy/output" ) //go:embed data //go:embed helloworld.txt var content embed.FS // EmbedFsMultifiles は、embed パッケージの機能を確認するサンプルです (embed.FSとして複数ファイルを操作) func EmbedFsMultifiles() error { var ( buf []byte err error ) // // 埋め込まれたファイルの操作 // buf, err = content.ReadFile("helloworld.txt") if err != nil { return err } output.Stdoutl("[helloworld.txt]", string(buf)) output.StdoutHr() // // 埋め込まれたディレクトリの操作 // entries, err := content.ReadDir("data") if err != nil { return err } for _, entry := range entries { if entry.IsDir() { continue } var ( name = entry.Name() path = fmt.Sprintf("data/%s", name) ) buf, err = content.ReadFile(path) if err != nil { return err } output.Stdoutl(fmt.Sprintf("[%s]", name), string(buf)) } return nil }
実行すると以下のようになります。
$ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime -example "" ENTER EXAMPLE NAME: embed_fs_multifile [Name] "embed_fs_multifiles" [helloworld.txt] hello world -------------------------------------------------- [dotnet.txt] dotnet [go.txt] golang [golang.txt] golang [python.txt] python [Elapsed] 261.159µs
ちゃんと動作していますね。実行時には当然 helloworld.txt も data ディレクトリも必要ありません。
注意点として、バイナリにはそのまま埋め込まれていますので、バイナリエディタとかで除くと当然丸見えです。センシティブなデータは埋め込まないようにしましょう。(しないと思いますが)
参考資料
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場