🎯 目标:让你的 ChitChat 留言板支持 CSS 样式、防止乱发帖,并实现简单的用户名登录!
✅ 1. 先解决"丑"的问题:加载 CSS 静态文件
现在你的留言板是纯文字,太朴素了。我们加个 CSS 让它好看点!
步骤一:创建静态资源目录
chitchat/
├── main.go
├── templates/
│ └── index.html
└── static/ ← 新建这个文件夹
└── style.css
步骤二:写个简单的 CSS(static/style.css)
css
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 40px auto;
padding: 20px;
background: #f9f9f9;
}
input[type="text"] {
width: 70%;
padding: 8px;
}
button {
padding: 8px 16px;
background: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
p {
background: white;
padding: 10px;
margin: 10px 0;
border-left: 4px solid #4CAF50;
}
步骤三:在 HTML 中引用 CSS(templates/index.html 头部加一行)
html
<head>
<title>ChitChat 留言板</title>
<link rel="stylesheet" href="/static/style.css"> <!-- 关键! -->
</head>
步骤四:让 Go 能"提供"静态文件
在 main.go 的 main() 函数里,加这一行:
go
// 在 http.HandleFunc 之前加:
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
💡 这行代码的意思是:
- 所有以
/static/开头的请求(比如/static/style.css)- 去
static/文件夹里找对应文件并返回
✅ 现在重启服务,刷新页面------是不是变漂亮了?
✅ 2. 防止乱发帖:表单内容校验
用户可能提交空内容、超长内容,我们要拦截!
修改 post 函数:
go
func post(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
content := r.FormValue("content")
content = strings.TrimSpace(content) // 去掉首尾空格
// 校验规则
if content == "" {
http.Error(w, "留言不能为空!", http.StatusBadRequest)
return
}
if len(content) > 200 {
http.Error(w, "留言不能超过200个字!", http.StatusBadRequest)
return
}
// 通过校验,才保存
msg := Message{
Content: content,
Time: time.Now().Format("2006-01-02 15:04"),
}
messages = append(messages, msg)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
别忘了在文件顶部导入 strings 包:
go
import (
...
"strings"
)
🔍 测试:
- 提交空内容 → 显示错误提示
- 输入 300 个字 → 拒绝提交
✅ 3. 实现"记住我":用 Cookie 实现简单登录
我们不想每次发帖都输名字,那就让用户首次输入名字后记住他!
步骤一:首页加一个"登录"表单(只在没登录时显示)
修改 templates/index.html:
html
{{if not .User}}
<div style="margin-bottom:20px;">
<form method="POST" action="/login">
<input type="text" name="username" placeholder="输入你的昵称" required>
<button type="submit">进入聊天室</button>
</form>
</div>
{{else}}
<h2>你好,{{.User}}!</h2>
<form method="POST" action="/post">
<input type="text" name="content" placeholder="写下你想说的..." required>
<button type="submit">发送</button>
</form>
{{end}}
注意:模板里用了
{``{if not .User}}判断是否已登录。
步骤二:改造 home 函数,传入用户名(从 Cookie 读)
go
func home(w http.ResponseWriter, r *http.Request) {
// 从 Cookie 读取用户名
var username string
cookie, err := r.Cookie("username")
if err == nil {
username = cookie.Value
}
// 构造传给模板的数据
data := struct {
User string
Messages []Message
}{
User: username,
Messages: messages,
}
tmpl := template.Must(template.ParseFiles("templates/index.html"))
tmpl.Execute(w, data)
}
步骤三:添加 /login 处理函数
go
func login(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
username := strings.TrimSpace(r.FormValue("username"))
if username == "" || len(username) > 20 {
http.Error(w, "昵称不能为空且不超过20字", http.StatusBadRequest)
return
}
// 设置 Cookie,有效期 24 小时
http.SetCookie(w, &http.Cookie{
Name: "username",
Value: username,
MaxAge: 3600 * 24, // 秒
Path: "/",
})
http.Redirect(w, r, "/", http.StatusSeeOther)
}
并在 main() 里注册路由:
go
http.HandleFunc("/login", login)
步骤四:发帖时也检查是否登录
修改 post 函数开头:
go
// 检查是否登录
cookie, err := r.Cookie("username")
if err != nil {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// 后续可以用 cookie.Value 获取用户名(比如存进 Message)
✅ 现在流程是:
- 首次访问 → 输入昵称 → 设置 Cookie
- 刷新页面 → 自动识别你是谁
- 只有登录用户才能发帖!
✅ 4. 安全小贴士(第3章重点!)
- 永远不要信任前端数据:即使前端写了"必填",后端也要校验。
- Cookie 不是安全的:用户可以改 Cookie!所以不能存密码、权限等敏感信息。
- 路径安全 :
http.FileServer要配合StripPrefix,否则可能被遍历服务器文件!
✅ 5. 本章核心收获(一句话总结)
| 功能 | Go 怎么做 |
|---|---|
| 提供 CSS/JS/图片 | http.FileServer + http.Handle("/static/", ...) |
| 表单校验 | r.FormValue() + if 判断 |
| 记住用户 | http.SetCookie() 和 r.Cookie() |
| 模板传多个数据 | 用匿名 struct { User string; Messages []Message } |
🔧 下一步挑战(可选)
- 把用户名也显示在每条留言旁边(修改
Message结构体,存Username字段)。 - 添加"退出登录"按钮:设置 Cookie 的
MaxAge = -1即可删除。 - 用
securecookie库对 Cookie 内容加密,防止用户伪造。
✅ 总结 :第3章让你的网站从"能用"变成"好用又安全"。
静态资源、表单处理、用户状态------这些都是真实项目天天打交道的东西。
现在你的 ChitChat 已经像个正经网站了!