概要
GolangでTemplateを使った場合、実行ファイルと一緒にテンプレートファイルを配布する必要があります。
Statikライブラリを使わずに実行ファイルだけ配布すると以下のようなエラーが発生します。
panic: open ./hello_message.tmpl: The system cannot find the path specified.
Statikライブラリを使うと実行ファイルのバイナリにテンプレートファイルも一緒にビルドして配布することができるので今回はサンプルを作ってやってみます。
Statik設置
$go get github.com/rakyll/statik
詳細内容は以下のリンク参照
https://github.com/rakyll/statik
サンプルコードでやってみる!
Goプロジェクト生成
$mkdir template_project
$ go mod init hello
$ vi hello.go
hello.go作成
hello.go
package main
import (
"fmt"
"bytes"
"io/ioutil"
"path/filepath"
"text/template"
// 以下の2行がstatik関連import
_ "hello/statik" //statikフォルダのパス
"github.com/rakyll/statik/fs"
)
// Templateファイルに渡すデータを保存するStruct
type HelloTemplateRenderer struct {
Name string
}
func main() {
var tpl bytes.Buffer
helloTemplateRender := &HelloTemplateRenderer{Name: "Aki"}
hello_message, err := getDataFromFile("hello_message.tmpl")
if err != nil {
fmt.Println(err)
return
}
helloTmp, err := template.New("hello").Parse(hello_message)
if err != nil {
fmt.Println(err)
return
}
helloTmp.Execute(&tpl, helloTemplateRender)
fmt.Println(tpl.String())
return
}
// ファイル名からStatikファイルシステムを利用してファイル内容を取得
func getDataFromFile(fileName string) (string, error) {
filePath := filepath.Join("/", fileName)
fileSystem, err := fs.New()
if err != nil {
return "", err
}
file, err := fileSystem.Open(filePath)
if err != nil {
return "", err
}
defer file.Close()
fileContent, err := ioutil.ReadAll(file)
if err != nil {
return "", err
}
return string(fileContent), err
}
Templateファイル作成
template/hello_message.tmpl
Hello My name is {{.Name}}.
Statikファイル生成
$statik -src template
statikコマンドを実行すると以下のようにstatikフォルダの下にstatik.goが生成されます。
├── go.mod
├── go.sum
├── hello.go
├── statik
│ └── statik.go
└── template
└── hello_message.tmpl
Build
Buildして実行ファイルだけ他のフォルダにコピーして、テンプレートなくても実行可能かを確認しました。問題なく実行できました。
Mac用実行ファイル生成
Templateファイルと入力した名前が画面に表示されました。
mac
$go build -o hello hello.go
$ ./hello
Hello My name is Aki.
Windows用実行ファイル生成
windows
$GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build -o hello.exe hello.go