iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
Modern Web

Golang x Echo 30 天:零基礎GO , 後端入門系列 第 19

以 Go + Echo 打造部落格|第 3 篇:模板與靜態資源

  • 分享至 

  • xImage
  •  

以 Go + Echo 打造部落格|第 3 篇:模板與靜態資源(html/template + Tailwind CDN)

今天把畫面整理起來:用 html/template 做出 layout(版型)partial(可重用片段),再掛上 Tailwind CDN 讓頁面秒變清爽。完成後,你會有首頁的基本視覺、乾淨的模板結構,之後要加表單、清單、分頁都好上手 😄
小辭典:
layout:共用外框(像房子的骨架),各頁把內容塞進去就好。
partial:可重複使用的小區塊(例如導覽列、頁腳)。
CDN(Content Delivery Network):放在全球伺服器的檔案,讓你直接引用,不用下載到專案裡。


本篇要做到什麼?

  • 把模板拆成 layouts/partials/pages/ 三層,讓結構清楚
  • 在 layout 裡引入 Tailwind CDN(先用最省事的做法)
  • 首頁 / 用模板渲染:標題、站名、現在時間
  • 靜態檔(/static)可放圖片、favicon 等

步驟清單(骨架 → 填充)

1) 建立模板目錄與檔案骨架

mkdir -p web/templates/layouts web/templates/partials web/templates/pages

web/templates/layouts/base.html(骨架)

{{ define "layouts/base" -}}
<!doctype html>
<html lang="zh-Hant">
<head>
  <meta charset="utf-8">
  <title>{{ block "title" . }}{{ .Title }} • {{ .SiteName }}{{ end }}</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- Tailwind CDN(方便先上手;未來可改本地 build) -->
  <script src="https://cdn.tailwindcss.com"></script>

  <!-- 你自己的靜態檔(logo、favicon 等) -->
  <link rel="icon" href="/static/favicon.ico">
</head>
<body class="min-h-screen bg-slate-50 text-slate-800">
  {{ template "partials/nav" . }}

  <main class="container mx-auto px-4 py-8">
    {{ block "content" . }}{{ end }}
  </main>

  {{ template "partials/footer" . }}
</body>
</html>
{{- end }}

web/templates/partials/nav.html(導覽)

{{ define "partials/nav" -}}
<header class="border-b bg-white">
  <div class="container mx-auto px-4 py-4 flex items-center justify-between">
    <a href="/" class="flex items-center gap-3 font-semibold text-slate-900 hover:opacity-80">
      <img src="/static/logo.svg" alt="logo" class="w-8 h-8">
      <span>{{ .SiteName }}</span>
    </a>
    <nav class="flex items-center gap-6 text-slate-600">
      <a class="hover:text-slate-900" href="/">首頁</a>
      <a class="hover:text-slate-900" href="/health">健康檢查</a>
      <a class="hover:text-slate-900" href="https://echo.labstack.com/" target="_blank" rel="noreferrer">Echo</a>
    </nav>
  </div>
</header>
{{- end }}

web/templates/partials/footer.html(頁腳)

{{ define "partials/footer" -}}
<footer class="border-t bg-white mt-12">
  <div class="container mx-auto px-4 py-8 text-sm text-slate-500">
    <p>© {{ .Year }} • {{ .SiteName }} • 以 Go + Echo 打造部落格</p>
  </div>
</footer>
{{- end }}

web/templates/pages/index.html(首頁內容)

{{ define "pages/index" -}}
{{ template "layouts/base" . }}

{{ define "title" -}}首頁{{ end }}

{{ define "content" -}}
  <section class="grid gap-6">
    <h1 class="text-3xl font-bold">👋 Hello Blog</h1>
    <p class="text-slate-600">
      這是你的最小可行首頁(MVP)。Tailwind 已掛好,之後我們會把文章列表、分頁、Tags 都加上來。
    </p>

    <div class="rounded-lg border bg-white p-4">
      <div class="text-sm text-slate-500">台北時間</div>
      <div class="text-xl font-mono">{{ .Now }}</div>
    </div>

    <div class="grid md:grid-cols-2 gap-4">
      <a href="/health" class="rounded-lg border bg-white p-4 hover:shadow">
        <div class="font-semibold">健康檢查(JSON)</div>
        <div class="text-slate-500 text-sm">看看服務有沒有醒著 😴 → 😎</div>
      </a>
      <a href="/_ping" class="rounded-lg border bg白 p-4 hover:shadow">
        <div class="font-semibold">Ping(純文字)</div>
        <div class="text-slate-500 text-sm">只要回 pong 就代表連得上</div>
      </a>
    </div>
  </section>
{{- end }}
{{- end }}

2) 放幾個靜態檔(logo、favicon)

mkdir -p web/static

web/static/logo.svg(超迷你示意)

<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none">
  <rect x="3" y="3" width="18" height="18" rx="4" stroke="#0ea5e9" stroke-width="2"/>
  <path d="M7 12h10M12 7v10" stroke="#0ea5e9" stroke-width="2" stroke-linecap="round"/>
</svg>

web/static/favicon.ico
隨意放一個小圖示(如果沒有,也不會壞)。


3) 更新後端:讓 html/template 讀得到多層資料夾

cmd/server/main.go 的模板解析從 web/templates/*.html 改成 讀整個樹

cmd/server/main.go(完整可執行版本)

// ...(內容與教學相同,略)

internal/http/handlers/home.go(更新:帶 SiteName、Year,渲染 pages/index)

// ...(內容與教學相同,略)

4) 目錄樹(新增或更新以 ★ 標示)

go-echo-blog/
├─ cmd/
│  └─ server/
│     └─ main.go                 ★ 更新(ParseGlob **/*.html、HomeHandlerWithMeta)
├─ internal/
│  ├─ http/
│  │  └─ handlers/
│  │     └─ home.go              ★ 更新(提供 SiteName/Year,渲染 pages/index)
│  └─ storage/
│     └─ postgres/
│        └─ db.go
├─ web/
│  ├─ static/
│  │  ├─ logo.svg                ★ 新增
│  │  └─ favicon.ico             ★ 建議放
│  └─ templates/
│     ├─ layouts/
│     │  └─ base.html            ★ 新增
│     ├─ partials/
│     │  ├─ nav.html             ★ 新增
│     │  └─ footer.html          ★ 新增
│     └─ pages/
│        └─ index.html           ★ 新增
├─ migrations/
├─ docker-compose.yml
├─ .env
├─ .env.example
├─ Makefile
└─ go.mod

資料庫變更

本篇 不需要遷移(主打版面與模板)。


測試區(curl / Browser)

啟動:

make run

首頁(HTML):

curl -i http://localhost:1323/ | head -n 15

檢查 Tailwind 是否載入:

curl -s http://localhost:1323/ | grep -o 'cdn.tailwindcss.com' || echo "not found"

健康檢查(JSON):

curl -s http://localhost:1323/health | jq .

Ping(純文字):

curl -s http://localhost:1323/_ping
# pong

常見坑(排雷)🧯

  1. 模板找不到:ParseGlob("web/templates/**/*.html") 少了 **/* 就只會吃到單層。
  2. no such template "pages/index.html":檔名或資料夾層級打錯;或 define 名稱沒對到。
  3. Tailwind 沒生效:公司網路擋 CDN;可改用本地 build。

小結 & 下一篇

首頁有 layout、partial、Tailwind,資料與畫面分工清楚 ✅
下一篇:文章 CRUD(API + 後台 UI)MVP:/admin/posts 新增/查/改/刪 + 表單驗證與 CSRF。


上一篇
以 Go + Echo 打造部落格|第 2 篇 Postgres + pgxpool + goose
下一篇
以 Go + Echo 打造部落格|第 4 篇:文章 CRUD
系列文
Golang x Echo 30 天:零基礎GO , 後端入門24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言