LoginSignup
6
5

More than 3 years have passed since last update.

[Go] 1.16 から使える embed で HTML がバイナリに埋め込める!!

Last updated at Posted at 2021-02-19

シングルバイナリーがメリットと言われてる Go 言語ですが、HTML などのテンプレートはそのバイナリは埋め込むことができませんでした。
(hugo のようにファイルを生成するツールがあるので、無理くり、埋め込むことはできたんだと思いますが。。)

追記(2020/03/10): こちらの YouTube 動画 にて、1.16 より前の静的ファイルの埋め込み方法が解説されています。(ざっくりと、var embedData = []byte("静的ファイルの中身") が定義された Go ファイルを作成して build する。なるほどですね。)

ただ、Go 1.16 から go:embed を使うことで、めっちゃ簡単に埋め込むことができるようになりました!!

インポートした後は、これまで通り http/template が使えます!

めっちゃ便利なので、おすすめです。

以下、ざっくりとまとめです。

参考

https://golang.org/pkg/embed/
https://golang.org/pkg/html/template/

フォルダ配下全てを読み込み

下記のように書くことで、templates フォルダ配下のファイルを読み込みできます。
その後は、f を経由してアクセスできるようになります。

//go:embed templates
var f embed.FS

そう!これだけ!

読み込んだテンプレートを使う

template.ParseFS() を使って、インポートした特定の HTML を呼び出します。

tmpl, _ := template.ParseFS(f, "templates/index.html")

あとは、これまで通り Execute() で http.ResponreWriter に書き込み

// ここはこれまで通り
err := tmpl.Execute(w, "Second Page")

めっちゃ簡単!!

コード全体

main.go
package main

import (
    "embed"
    "html/template"
    "log"
    "net/http"
)

//go:embed templates
var f embed.FS

func index(w http.ResponseWriter, r *http.Request) {
    tmpl, _ := template.ParseFS(f, "templates/index.html")

    type Post struct {
        PageTitle   string
        PageContent string
    }

    // Struct データを渡してみる
    err := tmpl.Execute(w, &Post{PageTitle: "Index Page", PageContent: "トップページのコンテンツ"})
    if err != nil {
        log.Println(err)
    }
}

func second(w http.ResponseWriter, r *http.Request) {
    // base.html ばベースのテンプレートになるので、同時にパース
    tmpl, _ := template.ParseFS(f, "templates/second.html", "templates/base.html")

    // シンプルにテキスト文字列を渡してみる
    err := tmpl.Execute(w, "Second Page")
    if err != nil {
        log.Println(err)
    }
}

func main() {

    http.HandleFunc("/", index)
    http.HandleFunc("/second", second)

    log.Println("listening ... ")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal(err)
    }
}

確認①: テンプレートにデータを渡すことができる

index.html ページでは渡された struct データを受け取り、使うことができます

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name={{.}}>
    <title>{{ .PageTitle }}</title>
</head>
<body>

    <h1> {{ .PageContent }}</h1>

</body>
</html>

確認②: ベーステンプレートを使うこともできる

base.html
{{ define "base" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ . }}</title>
</head>
<body>

    {{template "content" . }}

</body>
</html>
{{ end }}

このベーステンプレートを使って、second.html を書く

second.html
{{ template "base" . }}

{{ define "content" }}
<h1>Welcome to Second Page</h1>
{{ end }}
6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5