Go 1.16の新機能 embedを試す

公開:2021/02/22
更新:2021/02/23
2 min読了の目安(約2200字TECH技術記事

Go 1.16の新機能として、ビルドしたバイナリ内にファイルを埋め込む機能が付きました。

これの何が嬉しいかというと、通常はバイナリの他に必要なファイル(CSSファイル、jsファイル、その他諸々)があるので一緒にコピーする必要があるのですが、コピーし忘れたりファイルを間違えて書換えたりなど、ヒューマンエラーが発生する可能性がありました。

新機能のembed機能を使うことで必要なファイルをディレクトリ構造を保持したまま埋め込めるので、

  • リソースをコピーする手間が減る
  • 必要なファイルを間違って消す・書き換えることが無くなる

というメリットが出てきます。
また、メモリ上にファイルシステムが構成されるので、ディスクから読み取るよりもパフォーマンスの向上が期待できます。

2021年2月16日にGo 1.16がリリースされましたので、インストールして試してみました。

環境

  • Windows 10 Home 20H2
  1. https://golang.org/dl/ のStable Versionsにある1.16からmsiファイルをダウンロード
  2. msiファイルをダブルクリックしてインストーラを起動、必要であればインストール先を変更してインストール
  3. コマンドプロンプトを起動してバージョン確認
>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だけになるので社内向けの小さいアプリの配布等に最適ですね。