TemplでGoのHTMLレンダリングを快適に!型安全なコンポーネント指向テンプレートエンジンの魅力
「GoでWebアプリを作るとき、HTMLのレンダリングってどうしてますか?」
標準パッケージの html/template は非常に強力で広く使われていますが、「型安全じゃない」「コンポーネントの再利用がしにくい」「エディタの補完が効かない」といった点で、少しモヤモヤすることはありませんか?特にReactやVueなどのモダンなフロントエンドフレームワークに慣れていると、そのギャップを強く感じるかもしれません。
そんな悩みを一気に解決してくれるのが、今回紹介する Templ です!
Templは、GoのためのHTMLテンプレート言語であり、JSXライクな構文でGoのコードとHTMLをシームレスに記述できる画期的なツールです。GitHubリポジトリでは 10,000以上のスターを獲得しており(2026年3月時点)、Go界隈でじわじわと注目度が上がっています。この記事では、Templの魅力から基本的な使い方、そして開発を快適にするコマンドや設定項目までをたっぷり解説します。
Templとは?
Templは、Go言語でHTMLユーザーインターフェースを構築するためのテンプレート言語です。.templ という拡張子のファイルにHTMLとGoのコードを混在させて書き、それを専用のCLIツールで純粋なGoのコードにコンパイルします。
公式サイトでは以下のように説明されています。
Create components that render fragments of HTML and compose them to create screens, pages, documents, or apps.
(HTMLの断片をレンダリングするコンポーネントを作成し、それらを組み合わせて画面、ページ、ドキュメント、またはアプリを作成します。)
最もシンプルなTemplコンポーネントはこんな感じです。
package main
templ Hello(name string) {
<div>Hello, { name }</div>
}
templ Greeting(person Person) {
<div class="greeting">
@Hello(person.Name)
</div>
}
@ を使って別のコンポーネントを呼び出せるのが特徴的ですね。
Templの主な特徴
Templが多くのGo開発者から注目を集めているのには、いくつかの明確な理由があります。公式サイトでは以下の特徴が挙げられています。
| 特徴 | 説明 |
|---|---|
| Server-side rendering | サーバーレス関数、Dockerコンテナ、通常のGoプログラムとしてデプロイ可能 |
| Static rendering | 静的HTMLファイルを生成して自由にデプロイ可能 |
| Compiled code | コンポーネントは高パフォーマンスなGoコードにコンパイルされる |
| Use Go | 任意のGoコードを呼び出せ、if、switch、for文をそのまま使える |
| No JavaScript | クライアント・サーバーサイドのJavaScriptが不要 |
| Great developer experience | IDEのオートコンプリートに対応 |
特に「型安全」という点が大きな強みです。テンプレートがGoのコードにコンパイルされるため、変数名の間違いや型の不一致はコンパイルエラーとして事前に検知されます。実行時にテンプレートのパースエラーで落ちる心配がありません。
また、最近流行りの htmx との相性も抜群で、Go + Templ + htmx のスタックは非常に強力な選択肢として注目されています。
クイックスタート:実際に動かしてみよう
百聞は一見に如かず。実際にTemplを使って簡単なWebサーバーを立ち上げてみましょう。
1. インストール
まずはプロジェクトをセットアップし、TemplのCLIツールをインストールします。
mkdir templ-hello
cd templ-hello
go mod init example.com/templ-hello
go get github.com/a-h/templ
グローバルインストール(Go 1.24以降推奨)
go install github.com/a-h/templ/cmd/templ@latest
これで templ コマンドがPATHに追加されます。
プロジェクトローカルインストール(Go 1.24の tool ディレクティブを使用)
go get -tool github.com/a-h/templ/cmd/templ@latest
この場合は templ の代わりに go tool templ を使います。
2. コンポーネントの作成
hello.templ というファイルを作成し、以下のコードを記述します。
package main
templ hello(name string) {
<div>Hello, { name }!</div>
}
非常にシンプルですね。templ キーワードを使ってコンポーネントを定義し、引数として name string を受け取っています。HTMLの中では { } で囲むことでGoの変数を展開できます。
3. Goコードの生成
以下のコマンドを実行して、.templ ファイルからGoのコードを生成します。
templ generate
すると、同じディレクトリに hello_templ.go というファイルが生成されます。この中には、hello 関数が templ.Component インターフェースを返すGoのコードが含まれています。
templ.Component は以下のインターフェースを実装しています。
type Component interface {
Render(ctx context.Context, w io.Writer) error
}
4. Webサーバーでレンダリング
生成されたコンポーネントを net/http を使ってブラウザに返してみましょう。main.go を作成します。
package main
import (
"fmt"
"net/http"
"github.com/a-h/templ"
)
func main() {
// コンポーネントの初期化
component := hello("Zenn Reader")
// templ.Handlerを使ってHTTPハンドラに変換
http.Handle("/", templ.Handler(component))
fmt.Println("Listening on :3000")
http.ListenAndServe(":3000", nil)
}
実行してみましょう。
go run .
ブラウザで http://localhost:3000 にアクセスすると、「Hello, Zenn Reader!」と表示されるはずです!
構文の基本と便利な機能
Templの構文は直感的で、Goを書ける人ならすぐに馴染むことができます。
パッケージ宣言とインポート
.templ ファイルの先頭は、通常のGoファイルと同様にパッケージ名とインポートから始まります。
package main
import "fmt"
import "time"
制御構文(if, switch, for)
テンプレート内でGoの標準的な制御構文をそのまま使用できます。特別なプレフィックスなどは必要ありません。
templ UserProfile(user User) {
<div class="profile">
<h1>{ user.Name }</h1>
if user.IsAdmin {
<span class="badge badge-admin">Admin</span>
} else {
<span class="badge">User</span>
}
<ul>
for _, role := range user.Roles {
<li>{ role }</li>
}
</ul>
</div>
}
動的な属性とCSSクラスの管理
クラス名を動的に切り替える場合、templ.KV が非常に便利です。templ.KV("クラス名", bool値) の形式で、true のときだけクラスが付与されます。
templ Button(text string, isPrimary bool) {
<button class={ "btn", templ.KV("btn-primary", isPrimary) }>
{ text }
</button>
}
スタイル属性でも同様に使えます。
templ TextInput(value string, hasError bool) {
<input
type="text"
value={ value }
style={
templ.KV("border-color: #ff3860", hasError),
templ.KV("background-color: #fff5f7", hasError),
"padding: 0.5em 1em;",
}
>
}
セキュリティ:自動エスケープとURLサニタイズ
Templは、動的な値を自動的にHTMLエスケープします。これにより、XSS(クロスサイトスクリプティング)攻撃を防ぐことができます。
URLも自動でサニタイズされ、javascript: などの危険なプロトコルは about:invalid#TemplFailedSanitizationURL に置き換えられます。
templ component(p Person) {
// hrefに渡されるURLは自動でサニタイズされる
<a href={ p.URL }>{ p.Name }</a>
}
サニタイズをバイパスしたい場合は templ.SafeURL() を使いますが、セキュリティリスクが生じる可能性があるため注意が必要です。
コンポーネントの合成(Composition)
Templの真価は、コンポーネントを組み合わせて複雑なUIを構築できる点にあります。
他のコンポーネントを呼び出す
@ 記号を使って、別のコンポーネントを呼び出すことができます。
templ showAll() {
@left()
@middle()
@right()
}
templ left() {
<div>Left</div>
}
templ middle() {
<div>Middle</div>
}
templ right() {
<div>Right</div>
}
子コンポーネントを渡す(Children)
{ children... } を使うことで、ラップするレイアウトコンポーネントを作成できます。
templ Layout(title string) {
<html>
<head><title>{ title }</title></head>
<body>
<header>My App</header>
<main>
{ children... }
</main>
<footer>© 2026 My App</footer>
</body>
</html>
}
templ HomePage() {
@Layout("Home") {
<h1>Welcome to the Home Page</h1>
<p>This is the main content.</p>
}
}
コンポーネントを引数として渡す
templ.Component 型を引数として受け取ることで、コンポーネントをパラメータとして渡すこともできます。
templ layout(contents templ.Component) {
<div id="heading">
<h1>My App</h1>
</div>
<div id="contents">
@contents
</div>
}
templ paragraph(text string) {
<p>{ text }</p>
}
templ root() {
@layout(paragraph("Dynamic contents"))
}
コンポーネントの公開・非公開
Templは、Goの命名規則に従います。大文字で始まるコンポーネントは公開(Public)、小文字で始まるコンポーネントは非公開(Private)です。
// 公開コンポーネント(他パッケージからも使える)
templ PublicHeader(title string) {
<header><h1>{ title }</h1></header>
}
// 非公開コンポーネント(同パッケージ内のみ)
templ privateFooter() {
<footer>© 2026</footer>
}
別パッケージのコンポーネントを使う場合は、通常のGoのインポートと同じです。
package main
import "github.com/yourname/yourapp/components"
templ Home() {
@components.PublicHeader("Welcome")
}
コマンドリファレンス
CLIコマンド一覧
templ コマンドには以下のサブコマンドがあります。
usage: templ <command> [<args>...]
templ - build HTML UIs with Go
commands:
generate Generates Go code from templ files
fmt Formats templ files
lsp Starts a language server for templ files
info Displays information about the templ environment
version Prints the version
| コマンド | 説明 |
|---|---|
templ generate |
カレントディレクトリ以下の .templ ファイルからGoコードを生成 |
templ generate -f header.templ |
指定したファイルのみGoコードを生成 |
templ generate -watch |
ファイルの変更を監視し、保存時に自動再生成 |
templ fmt . |
カレントディレクトリ以下の .templ ファイルをフォーマット |
templ fmt -fail . |
フォーマットが必要なファイルがあれば終了コード1で終了(CI向け) |
templ lsp |
Language Serverを起動(通常はエディタ拡張から自動起動) |
templ info |
templ環境の情報を表示 |
templ version |
バージョンを表示 |
templ generate の主要オプション
| オプション | デフォルト | 説明 |
|---|---|---|
-path <path> |
.(カレント) |
指定パス以下のファイルを対象にする |
-f <file> |
— | 単一ファイルのみ生成 |
-watch |
false |
ファイル変更を監視して自動再生成 |
-cmd <cmd> |
— | 生成後に実行するコマンド |
-proxy <url> |
— | 生成・コマンド実行後にプロキシするURL |
-proxyport |
7331 |
プロキシのリッスンポート |
-proxybind |
127.0.0.1 |
プロキシのバインドアドレス |
-w |
CPU数 | 並列ワーカー数 |
-lazy |
false |
.templ が .go より新しい場合のみ生成 |
-v |
— | デバッグログを有効化(-log-level debug と同等) |
-log-level |
info |
ログレベル(debug/info/warn/error) |
-include-version |
true |
生成コードにtemplバージョンを含めるか |
-keep-orphaned-files |
false |
孤立した生成ファイルを保持するか |
ライブリロード(開発時の必須コマンド)
開発中は以下のコマンドを使うと非常に快適です。ファイルを保存するたびに自動でコード生成・サーバー再起動・ブラウザリロードが行われます。
templ generate --watch --proxy="http://localhost:8080" --cmd="go run ."
このコマンドは以下を自動で行います。
-
.templファイルの変更を検知して自動でGoコードを再生成 -
.goファイルの変更を検知してWebサーバーを自動再起動 -
localhost:7331にプロキシを立ち上げ、ブラウザを自動リロード
エディタ設定
VS Code
VS Codeを使用している場合は、公式の拡張機能 「templ」(a-h.templ)をインストールするだけで、LSPによる強力なサポートを受けられます。
settings.json に以下の設定を追加することをおすすめします。
保存時の自動フォーマット
{
"editor.formatOnSave": true,
"[templ]": {
"editor.defaultFormatter": "a-h.templ"
}
}
Tailwind CSS Intellisenseの補完を有効化
{
"tailwindCSS.includeLanguages": {
"templ": "html"
}
}
Emmetの有効化
{
"emmet.includeLanguages": {
"templ": "html"
}
}
Neovim
Neovimでは、nvim-treesitter を使ってシンタックスハイライトを有効化できます。
:TSInstall templ
LSPの設定は lspconfig を使って行います。
local lspconfig = require("lspconfig")
-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
local servers = { 'gopls', 'ccls', 'cmake', 'tsserver', 'templ' }
for _, lsp in ipairs(servers) do
lspconfig[lsp].setup({
on_attach = on_attach,
capabilities = capabilities,
})
end
-- .templファイルの拡張子を登録(他のLSPが.templを認識するためにも必要)
vim.filetype.add({ extension = { templ = "templ" } })
保存時の自動フォーマットを設定する場合はこちら。
vim.api.nvim_create_autocmd({ "BufWritePre" }, {
pattern = { "*.templ" },
callback = vim.lsp.buf.format
})
JetBrains(IntelliJ / GoLand)
JetBrains IDEを使っている方向けのプラグインも提供されています。
まとめ
Templは、Go言語におけるHTMLレンダリングの体験を劇的に向上させるツールです。
- コンパイル時の型チェックによる安全性
- コンポーネント指向による高い再利用性
- LSPサポートによる快適なコーディング体験
- JavaScript不要でシンプルなアーキテクチャ
これらが揃っているため、特にGoをバックエンドとしたフルスタック開発(htmxなどとの組み合わせ)において、非常に強力な選択肢となります。
標準の html/template で「ちょっと書きづらいな…」と感じたことがある方は、ぜひ一度Templを試してみてください。きっとその快適さに驚くはずです!
Discussion