HTTP 状态码
意义
每个状态码都是 HTTP 设计者对网络通讯中可能出现情况的假设和预判。它们相当于现实世界的信号灯,例如遇到 404 表示资源找不到,500 表示服务器挂了。这种共识是万维网高效率的基础之一。
HTTP 状态码是日常开发和修改 Bug 的必备工具。常见状态码分类如下:
1. 必须掌握的状态码
- 200 OK: 请求完全正确,如打开网页、调用 API。
- 301 Moved Permanently: 资源永久迁移(例如访问 a.com 会重定向到 b.com)。
- 302 Found: 资源临时迁移。
- 400 Bad Request: 请求出错,如参数缺失。
- 401 Unauthorized: 未登录。
- 403 Forbidden: 已登录但无权限。
- 404 Not Found: 资源不存在。
- 500 Internal Server Error: 服务器内部错误。
2. 需要理解的状态码
排查问题时常用:
- 100 Continue
- 201 Created: 资源创建成功(POST)。
- 204 No Content: 处理成功但不返回资源(DELETE)。
- 206 Partial Content: 部分资源处理成功。
- 304 Not Modified: 资源未修改,可直接使用缓存。
- 405 Method Not Allowed: 方法不被允许。
- 408 Request Timeout: 请求超时。
- 502 Bad Gateway: 网关/代理收到无效响应。
- 503 Service Unavailable: 服务器暂不可用。
HTTP 协议
核心概念
1. HTTP 的本质
- 定义: 超文本传输协议。
- 核心模型: 【请求 + 响应】客户端发送请求,服务器响应,一问一答传递信息。
- 无状态: 服务器不会记住上一次请求(后期引入 Cookie、Session)。
- 位置: 应用层,规范客户端与服务器的传输格式和交互流程。
2. URL 结构
示例:https://www.example.com:8080/path?name=test#fragment
https: 协议类型。www.example.com: 域名(对应服务器 IP)。8080: 端口(http 默认 80,https 默认 443,可省略)。/path: 资源路径。?name=test: GET 携带的参数。#fragment: 锚点。
3. 请求方法 (Method)
- GET: 请求资源,不影响服务器资源。
- POST: 提交数据,在服务器创建新资源。
- PUT: 更新数据,若无资源则新建(幂等)。
- DELETE: 删除数据(通常返回 204)。
- PATCH: 修改部分资源(与 PUT 类似,但只更新部分)。
4. 状态码分类
- 1xx: 信息性状态码
- 2xx: 请求成功
- 3xx: 重定向
- 4xx: 客户端错误
- 5xx: 服务器错误
进阶知识
1. HTTP 版本演进
- HTTP/1.0: 每次访问重新建立连接。
- HTTP/1.1: 持久化连接,但只能串行发送请求。
- HTTP/2: 多路复用(一个连接同时发多个请求,互不阻塞)。
- HTTP/3: 引入 UDP,解决 TCP 队头堵塞问题。
2. 缓存机制
- 强缓存: 服务器通过
Cache-Control: max-age=3600告诉浏览器 1 小时内强制使用本地缓存。 - 协商缓存: 强缓存过期后,浏览器带
If-Modified-Since或Etag请求,服务器判断未修改则返回 304。
3. HTTPS 原理
HTTPS = HTTP + TLS。
- 核心区别: HTTP 明文传输,HTTPS 加密传输。
- SSL/TLS 作用:
- 加密: 将明文变为密文,防止截获破解。
- 身份认证: 验证服务器身份,防止钓鱼网站。
- 完整性校验: 确保信息未被篡改。
4. Cookie 和 Session
- Cookie: 服务器通过
Set-Cookie在客户端存储信息,解决 HTTP 无状态问题。 - Session: 服务端存储用户信息,与 Cookie 中的 SessionID 关联。
5. 跨域资源共享 (CORS)
- 跨域: 协议、域名、端口任一不同即属于不同域。
- 解决: 服务器返回
Access-Control-Allow-Origin响应头,允许指定域名跨域请求。
MySQL 的连接与增删改查
本篇通过 sqlx 包操作数据库。
连接
import (
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
// 核心步骤
DB, err := sqlx.Open("mysql", "root:1234@tcp(localhost:3306)/goweb?parseTime=true&loc=Local")
if err != nil {
// handle error
}
DB.Ping()
增删改查
queryCreate := "insert into user (id,name) values (?,?)"
queryDelete := "delete from user where id =?"
queryUpdate := "update user set name=? where id=?"
queryQuery := "select * from user"
// 执行
// 增:DB.Exec(queryCreate, 1, "白小纯")
// 删:DB.Exec(queryDelete, 1)
// 改:DB.Exec(queryUpdate, "夜藏", 1)
// 查:rows, err := DB.Query(queryQuery)
// for rows.Next() { rows.Scan(&id, &name) }
Cookie
起源与应用
Cookie 源于 Unix 中的 "magic cookie",用于程序间传递特定信息或状态。后端核心操作如下:
func serv(w http.ResponseWriter, r *http.Request) {
// 设置 Cookie
cookie := &http.Cookie{
Name: "session_id",
Value: "cookie",
Expires: time.Now().Add(time.Second),
}
http.SetCookie(w, cookie)
// 获取单个 Cookie
c, _ := r.Cookie("session_id")
fmt.Fprintln(w, c.Name, c.Value, c.Expires)
// 循环获取所有 Cookie
cs := r.Cookies()
for n, co := range cs {
fmt.Fprintln(w, n, co.Name)
}
}
Template
模板引擎用于解耦控制器 (Control) 与视图 (View),是 MVC 架构的关键组件。它包含占位符与控制逻辑,通过动态填充生成最终输出。
// 后端界面
func temp(w http.ResponseWriter, r *http.Request) {
add := template.FuncMap{"add": Add}
t := template.New("index").Funcs(add)
t, _ = t.ParseFiles("new_add")
t.Execute(w, nil)
}
前端模板语法示例:{{add 0 0}}
上传
从浏览器向服务器传输文件。
HTML 表单:
<form action="upload" enctype="multipart/form-data" method="post">
上传照片:<input type="file" name="photo">
</form>
Go 处理:
func upload(w http.ResponseWriter, r *http.Request) {
f, _, _ := r.FormFile("photo")
b, _ := io.ReadAll(f)
err := ioutil.WriteFile("/tmp/photo", b, 0777)
if err != nil {
fmt.Println("失败")
}
}
下载
<a href="download?filename=file.png">点击我下载</a>
func download(w http.ResponseWriter, r *http.Request) {
name := r.FormValue("filename")
data, _ := os.ReadFile("./files/" + name)
h := w.Header()
h.Set("Content-Type", "application/octet-stream")
h.Set("Content-Disposition", "attachment; filename=photo")
fmt.Fprint(w, data)
}
控制器
单控制器
type myStruct struct{}
func (m myStruct) ServeHTTP(w http.ResponseWriter, r *http.Request) {}
func main() {
s := http.Server{
Addr: "localhost:8888",
Handler: myStruct{},
}
s.ListenAndServe()
}
多控制器
func Test(w http.ResponseWriter, r *http.Request) {}
func main() {
server := http.Server{Addr: "localhost:8888"}
http.HandleFunc("/url", Test)
server.ListenAndServe()
}
GET 与 POST 核心区别
需着重注意语义、参数传递、幂等性、缓存等角度。
- 语义: GET 获取资源,POST 提交资源。
- 参数: GET 在 URL,POST 在请求体。
- 幂等性: GET 多次执行结果不变(幂等),POST 可能多次提交(非幂等)。
- 缓存: GET 易被缓存,POST 一般不缓存。


