1 net/http 基础
Go 标准库 net/http 提供了功能完备的 HTTP 服务器和客户端,无需任何第三方框架即可构建生产级 Web 服务。
最小 HTTP 服务器
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, Go!")
})
http.HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"message": "Hello, World!"}`)
})
fmt.Println("Server running on :8080")
http.ListenAndServe(":8080", nil)
}
请求方法判断与路由
package main
import (
"fmt"
"net/http"
)
func userHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
fmt.Fprintf(w, "获取用户列表")
case http.MethodPost:
fmt.Fprintf(w, "创建用户")
default:
http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
}
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/users", userHandler)
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "OK")
})
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
fmt.Println("Server running on :8080")
server.ListenAndServe()
}
🔄 Go net/http vs Node.js Express vs Python Flask
// Go:标准库即可,零依赖
http.HandleFunc("/api/users", handler)
http.ListenAndServe(":8080", nil)
# Node.js Express:需要安装框架
# const express = require('express');
# const app = express();
# app.get('/api/users', handler);
# app.listen(8080);
# Python Flask:需要安装框架
# from flask import Flask
# app = Flask(__name__)
# @app.route('/api/users')
# def handler(): ...
# app.run(port=8080)
Go 优势:标准库自带高性能 HTTP 服务器,无需框架依赖,编译为单一二进制文件部署极其简单。
2 JSON 处理
Go 通过 encoding/json 包提供 JSON 编解码支持,使用 struct tag 控制字段映射。
结构体与 JSON 映射
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email,omitempty"`
Age int `json:"age,omitempty"`
}
type ApiResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
Marshal / Unmarshal
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email,omitempty"`
}
func main() {
// 结构体 → JSON 字符串(Marshal)
user := User{ID: 1, Name: "张三", Email: "zhangsan@example.com"}
data, err := json.Marshal(user)
if err != nil {
panic(err)
}
fmt.Println(string(data))
// {"id":1,"name":"张三","email":"zhangsan@example.com"}
// 美化输出
pretty, _ := json.MarshalIndent(user, "", " ")
fmt.Println(string(pretty))
// JSON 字符串 → 结构体(Unmarshal)
jsonStr := `{"id":2,"name":"李四","email":"lisi@example.com"}`
var u User
err = json.Unmarshal([]byte(jsonStr), &u)
if err != nil {
panic(err)
}
fmt.Printf("ID: %d, Name: %s\n", u.ID, u.Name)
// 解析到 map(不确定结构时)
var result map[string]interface{}
json.Unmarshal([]byte(jsonStr), &result)
fmt.Println(result["name"]) // 李四
}
流式编解码:NewEncoder / NewDecoder
// 在 HTTP handler 中直接编码到 ResponseWriter
func getUser(w http.ResponseWriter, r *http.Request) {
user := User{ID: 1, Name: "张三", Email: "zhangsan@example.com"}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
}
// 从请求体直接解码
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "无效的 JSON", http.StatusBadRequest)
return
}
defer r.Body.Close()
fmt.Fprintf(w, "收到用户: %s", user.Name)
}
struct tag 常用选项:`json:"field_name"` 重命名字段;`json:"field,omitempty"` 零值时省略;`json:"-"` 忽略字段。
3 HTTP 客户端
简单 GET 请求
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
resp, err := http.Get("https://api.example.com/users")
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取失败:", err)
return
}
fmt.Println("状态码:", resp.StatusCode)
fmt.Println("响应:", string(body))
}
POST 请求发送 JSON
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
user := map[string]interface{}{
"name": "王五",
"email": "wangwu@example.com",
}
jsonData, _ := json.Marshal(user)
resp, err := http.Post(
"https://api.example.com/users",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println("状态码:", resp.StatusCode)
fmt.Println("响应:", string(body))
}
自定义 Client 与超时
package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
client := &http.Client{
Timeout: 10 * time.Second,
}
req, err := http.NewRequest("GET", "https://api.example.com/users", nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer your-token-here")
req.Header.Set("Accept", "application/json")
resp, err := client.Do(req)
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Printf("状态码: %d\n响应: %s\n", resp.StatusCode, body)
}
重要:始终记得 defer resp.Body.Close(),否则会导致连接泄漏。生产环境建议使用自定义 Client 而非默认的 http.DefaultClient(它没有超时限制)。
4 REST API 实践
以下是一个完整的用户 CRUD API 示例,展示路由分发、JSON 请求/响应处理的最佳实践。
package main
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"sync"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
var (
users = make(map[int]User)
nextID = 1
mu sync.Mutex
)
func jsonResponse(w http.ResponseWriter, data interface{}, status int) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(status)
json.NewEncoder(w).Encode(data)
}
func jsonError(w http.ResponseWriter, msg string, status int) {
jsonResponse(w, map[string]string{"error": msg}, status)
}
func usersHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
mu.Lock()
list := make([]User, 0, len(users))
for _, u := range users {
list = append(list, u)
}
mu.Unlock()
jsonResponse(w, list, http.StatusOK)
case http.MethodPost:
var u User
if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
jsonError(w, "无效的 JSON", http.StatusBadRequest)
return
}
if u.Name == "" || u.Email == "" {
jsonError(w, "name 和 email 为必填字段", http.StatusUnprocessableEntity)
return
}
mu.Lock()
u.ID = nextID
nextID++
users[u.ID] = u
mu.Unlock()
jsonResponse(w, u, http.StatusCreated)
default:
jsonError(w, "方法不允许", http.StatusMethodNotAllowed)
}
}
func userHandler(w http.ResponseWriter, r *http.Request) {
idStr := strings.TrimPrefix(r.URL.Path, "/api/users/")
id, err := strconv.Atoi(idStr)
if err != nil {
jsonError(w, "无效的用户 ID", http.StatusBadRequest)
return
}
switch r.Method {
case http.MethodGet:
mu.Lock()
u, ok := users[id]
mu.Unlock()
if !ok {
jsonError(w, "用户不存在", http.StatusNotFound)
return
}
jsonResponse(w, u, http.StatusOK)
case http.MethodPut:
var input User
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
jsonError(w, "无效的 JSON", http.StatusBadRequest)
return
}
mu.Lock()
if _, ok := users[id]; !ok {
mu.Unlock()
jsonError(w, "用户不存在", http.StatusNotFound)
return
}
input.ID = id
users[id] = input
mu.Unlock()
jsonResponse(w, input, http.StatusOK)
case http.MethodDelete:
mu.Lock()
if _, ok := users[id]; !ok {
mu.Unlock()
jsonError(w, "用户不存在", http.StatusNotFound)
return
}
delete(users, id)
mu.Unlock()
jsonResponse(w, map[string]string{"message": "删除成功"}, http.StatusOK)
default:
jsonError(w, "方法不允许", http.StatusMethodNotAllowed)
}
}
func main() {
http.HandleFunc("/api/users", usersHandler)
http.HandleFunc("/api/users/", userHandler)
fmt.Println("REST API running on :8080")
http.ListenAndServe(":8080", nil)
}
测试命令:
# 创建用户
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"name":"张三","email":"zhangsan@example.com"}'
# 获取用户列表
curl http://localhost:8080/api/users
# 获取单个用户
curl http://localhost:8080/api/users/1
# 更新用户
curl -X PUT http://localhost:8080/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"张三丰","email":"zsf@example.com"}'
# 删除用户
curl -X DELETE http://localhost:8080/api/users/1
5 中间件
Go 的中间件是一个接收 http.Handler 并返回 http.Handler 的函数,通过链式组合实现请求预处理。
中间件基本模式
type Middleware func(http.Handler) http.Handler
func Chain(handler http.Handler, middlewares ...Middleware) http.Handler {
for i := len(middlewares) - 1; i >= 0; i-- {
handler = middlewares[i](handler)
}
return handler
}
日志中间件
package main
import (
"fmt"
"log"
"net/http"
"time"
)
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf("%s %s %s", r.Method, r.URL.Path, time.Since(start))
})
}
func corsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusNoContent)
return
}
next.ServeHTTP(w, r)
})
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `{"message": "Hello!"}`)
})
handler := loggingMiddleware(corsMiddleware(mux))
fmt.Println("Server running on :8080")
http.ListenAndServe(":8080", handler)
}
认证中间件
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, `{"error":"缺少认证令牌"}`, http.StatusUnauthorized)
return
}
if !strings.HasPrefix(token, "Bearer ") {
http.Error(w, `{"error":"无效的令牌格式"}`, http.StatusUnauthorized)
return
}
tokenStr := strings.TrimPrefix(token, "Bearer ")
if !validateToken(tokenStr) {
http.Error(w, `{"error":"令牌无效或已过期"}`, http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func validateToken(token string) bool {
return token == "valid-secret-token"
}
// 使用:只保护需要认证的路由
// protectedMux := http.NewServeMux()
// protectedMux.HandleFunc("/api/admin", adminHandler)
// http.Handle("/api/admin", authMiddleware(protectedMux))
中间件链顺序很重要:外层中间件先执行。典型顺序为:恢复(Recovery) → 日志 → CORS → 认证 → 业务 Handler。
6 本章要点
🌐 HTTP 服务器
- •
http.HandleFunc注册路由 - •
http.ListenAndServe启动服务 - •
http.NewServeMux自定义路由器
📦 JSON 处理
- •
json.Marshal/json.Unmarshal - • struct tag 控制字段映射
- •
json.NewEncoder/json.NewDecoder
🔗 HTTP 客户端
- •
http.Get/http.Post快速请求 - •
http.NewRequest自定义请求 - • 自定义
http.Client设置超时
🔌 REST API
- • 按 Method 分发处理逻辑
- • 统一 JSON 响应格式
- • CRUD 路由约定
🧩 中间件
- • 函数签名:
func(http.Handler) http.Handler - • 日志、CORS、认证中间件
- • 链式组合,顺序敏感
💡 最佳实践
- • 始终
defer resp.Body.Close() - • 生产环境设置请求超时
- • 使用
http.Error返回错误