📝
Go 1.16の新機能 embedを試す
Go 1.16の新機能として、ビルドしたバイナリ内にファイルを埋め込む機能が付きました。
これの何が嬉しいかというと、通常はバイナリの他に必要なファイル(CSSファイル、jsファイル、その他諸々)があるので一緒にコピーする必要があるのですが、コピーし忘れたりファイルを間違えて書換えたりなど、ヒューマンエラーが発生する可能性がありました。
新機能のembed機能を使うことで必要なファイルをディレクトリ構造を保持したまま埋め込めるので、
- リソースをコピーする手間が減る
- 必要なファイルを間違って消す・書き換えることが無くなる
というメリットが出てきます。
また、メモリ上にファイルシステムが構成されるので、ディスクから読み取るよりもパフォーマンスの向上が期待できます。
2021年2月16日にGo 1.16がリリースされましたので、インストールして試してみました。
環境
- Windows 10 Home 20H2
- https://golang.org/dl/ のStable Versionsにある1.16からmsiファイルをダウンロード
- msiファイルをダブルクリックしてインストーラを起動、必要であればインストール先を変更してインストール
- コマンドプロンプトを起動してバージョン確認
>go version
go version go1.16 windows/amd64
試しに日本語フォントファイルをアプリの中に埋め込んだ日本語PDF生成アプリを作成していきます。
- PDFのライブラリは日本語フォントにも対応しているgopdfを使います。
https://github.com/signintech/gopdf - 日本語フォントはIPAex明朝とIPAexゴシックを (Ver.004.01)を使います。
今回のディレクトリ構造は以下のような形です。embedディレクトリ以下を埋め込みます。
ソースコードは以下の通りです。
package main
import (
"bytes"
"embed"
"log"
"path"
"github.com/signintech/gopdf"
)
//go:embed embed/*.*
var assets embed.FS
func main() {
//PDF準備
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
pdf.AddPage()
//ディレクトリ確認
direntry, err := assets.ReadDir("embed")
if err != nil {
log.Print(err.Error())
return
}
var fontnames []string
var fontname string
for _, fontfile := range direntry {
//フォントファイルを読み込んで登録。フォントの名称はフォントファイル名を採用
filepath := path.Join("embed", fontfile.Name())
filebyte, err := assets.ReadFile(filepath)
if err != nil {
log.Print(err.Error())
return
}
rd := bytes.NewReader(filebyte)
fontname = fontfile.Name()
fontnames = append(fontnames, fontname)
err = pdf.AddTTFFontByReader(fontname, rd)
if err != nil {
log.Print(err.Error())
return
}
}
var yOffset float64
for idx, fn := range fontnames {
err = pdf.SetFont(fn, "", 14)
if err != nil {
log.Print(err.Error())
return
}
yOffset = 50 * (1 + float64(idx))
pdf.SetX(1.0)
pdf.SetY(yOffset)
pdf.Text("こんにちは.Go embed fontfile(" + fn + ")")
}
pdf.WritePdf("helloEmbed.pdf")
}
実行すると下記の通り、日本語PDFが生成されます。
EXEのサイズが膨らみますが、配布物がEXEだけになるので社内向けの小さいアプリの配布等に最適ですね。
Discussion