Goaサービスは、Goの標準html/template
パッケージを使用して動的HTMLコンテンツを
レンダリングできます。このガイドでは、テンプレートレンダリングをGoaサービスに
統合する方法を説明します。
まず、HTMLテンプレートをレンダリングするサービスエンドポイントを定義します:
package design
import . "goa.design/goa/v3/dsl"
var _ = Service("front", func() {
Description("テンプレートレンダリングを行うフロントエンドWebサービス")
Method("home", func() {
Description("ホームページをレンダリングします")
Payload(func() {
Field(1, "name", String, "ホームページに表示する名前")
Required("name")
})
Result(Bytes)
HTTP(func() {
GET("/")
Response(StatusOK, func() {
ContentType("text/html")
})
})
})
})
テンプレートレンダリングを管理するサービスを作成します:
package front
import (
"context"
"embed"
"html/template"
"bytes"
"fmt"
genfront "myapp/gen/front" // 生成されたパッケージ名に置き換えてください
)
//go:embed templates/*.html
var templateFS embed.FS
type Service struct {
tmpl *template.Template
}
func New() (*Service, error) {
tmpl, err := template.ParseFS(templateFS, "templates/*.html")
if err != nil {
return nil, fmt.Errorf("テンプレートの解析に失敗しました: %w", err)
}
return &Service{tmpl: tmpl}, nil
}
テンプレートをレンダリングするサービスメソッドを実装します:
func (svc *Service) Home(ctx context.Context, p *genfront.HomePayload) ([]byte, error) {
// テンプレート用のデータを準備
data := map[string]interface{}{
"Title": "ようこそ",
"Content": p.Name + "さん、ようこそ!",
}
// レンダリングされたテンプレートを格納するバッファを作成
var buf bytes.Buffer
// テンプレートをバッファにレンダリング
if err := svc.tmpl.ExecuteTemplate(&buf, "home.html", data); err != nil {
return nil, fmt.Errorf("テンプレートのレンダリングに失敗しました: %w", err)
}
return buf.Bytes(), nil
}
templates
ディレクトリにHTMLテンプレートを作成します:
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
</head>
<body>
{{block "content" .}}{{end}}
</body>
</html>
<!-- templates/home.html -->
{{template "base.html" .}}
{{define "content"}}
<h1>{{.Title}}</h1>
<p>{{.Content}}</p>
{{end}}
テンプレートサービスでサーバーをセットアップします:
func main() {
// サービスを作成
svc := front.New()
// HTTPサーバーを初期化
endpoints := genfront.NewEndpoints(svc)
mux := goahttp.NewMuxer()
server := genserver.New(endpoints, mux, goahttp.RequestDecoder, goahttp.ResponseEncoder, nil, nil)
genserver.Mount(server, mux)
// サーバーを起動
if err := http.ListenAndServe(":8080", mux); err != nil {
log.Fatalf("サーバーの起動に失敗しました: %v", err)
}
}
静的ファイルと動的テンプレートの両方を提供する必要がある場合、サービスデザインで それらを組み合わせることができます:
var _ = Service("front", func() {
// 動的テンプレートエンドポイント
Method("home", func() {
HTTP(func() {
GET("/")
Response(StatusOK, func() {
ContentType("text/html")
})
})
})
// 静的ファイルの提供
Files("/static/{*filepath}", "public/static")
})
このセットアップは以下を提供します:
テンプレートの構成
エラー処理
パフォーマンス