Go 标准库 net/http 包是干嘛的?
net/http 是 Go 官方自带的 HTTP 框架,不用装任何第三方库,直接就能写:
- HTTP 服务端(写接口、网站、API)
- HTTP 客户端(发请求、调用别人接口)
服务端
核心 API
http.HandleFunc(pattern, handler): 注册路由(将路径和对应的函数绑定)。http.ListenAndServe(addr, handler): 启动监听并服务。http.ResponseWriter: 用于向客户端写入响应(写回数据)。*http.Request: 包含客户端发来的所有信息(URL、Header、参数等)。
go
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
// r.Method 可以判断是 GET 还是 POST
fmt.Fprintf(w, "你好,你访问的路径是: %s", r.URL.Path)
}
func main() {
// 1. 路由注册
http.HandleFunc("/", helloHandler)
// 2. 启动服务,监听 8080 端口
fmt.Println("服务器启动在 http://localhost:8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
panic(err)
}
}
HandleFunc 与接口函数
go
// `net/http` 定义了一个接口
type Handler interface {
ServeHTTP(w http.ResponseWriter, r *http.Request)
}
func(w http.ResponseWriter, r *http.Request)
w http.ResponseWriter 给客户端返回数据(写响应)
go
w.Write([]byte("返回内容"))
w.WriteHeader(404) // 设置状态码
fmt.Fprintln(w, "hello") // 也可以这样写
r *http.Request 获取客户端传过来的东西
- URL 参数
- POST 表单 / JSON
- 请求头
- 请求方法(GET/POST)
常用的 5 种HandleFunc用法
处理 GET 请求(获取 URL 参数)
go
http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
// 获取 ?name=xxx & age=xxx
name := r.URL.Query().Get("name")
age := r.URL.Query().Get("age")
w.Write([]byte("名字:" + name + " 年龄:" + age))
})
处理 POST 表单(前端提交数据)
go
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
// 解析 POST 表单
r.ParseForm()
// 获取表单参数
username := r.PostForm.Get("username")
password := r.PostForm.Get("password")
w.Write([]byte("用户名:" + username + " 密码:" + password))
})
返回 JSON(写 API 接口)
go
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
http.HandleFunc("/json", func(w http.ResponseWriter, r *http.Request) {
user := User{Name: "张三", Age: 20}
// 设置返回格式 JSON
w.Header().Set("Content-Type", "application/json")
// 编码并返回
json.NewEncoder(w).Encode(user)
})
路由分组 / 多个接口
go
// 首页
http.HandleFunc("/", homeHandler)
// 用户相关
http.HandleFunc("/user/list", userListHandler)
http.HandleFunc("/user/info", userInfoHandler)
// 登录
http.HandleFunc("/login", loginHandler)
访问静态文件服务
go
// 访问 /static/ 下的文件
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
ServeMux 与自定义 Handler
go
mux := http.NewServeMux()
mux.HandleFunc("/user", userHandler)
// 将 mux 传入 ListenAndServe
http.ListenAndServe(":8080", mux)
直接使用 http.HandleFunc (默认模式)
当你直接调用 http.HandleFunc 时,Go 会在后台使用一个全局默认的实例,叫 DefaultServeMux。
- 优点:代码少,写个小脚本测试非常快。
- 缺点 :它是全局共享 的。如果你引入的第三方库也偷偷在
DefaultServeMux上注册了路由,可能会产生冲突。此外,在单元测试中,全局变量会让测试变得互相干扰。
使用 http.NewServeMux() (自定义模式)
当你创建自己的 mux 时,你是在创建一个隔离的路由表。
- 优点 :更安全、更灵活。你可以创建多个
mux,分别跑在不同的端口上,或者在测试时轻松地替换它。
go
package main
import (
"fmt"
"net/http"
)
func main() {
// --- 局部变量 1:给普通用户的路由 ---
userMux := http.NewServeMux()
userMux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "这是【普通用户】的个人中心")
})
// --- 局部变量 2:给管理员的路由 ---
adminMux := http.NewServeMux()
adminMux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "这是【管理员】的用户管理界面")
})
// 在 8080 端口启动用户服务
go http.ListenAndServe(":8080", userMux)
// 在 9090 端口启动管理服务
fmt.Println("服务已启动:8080 为用户,9090 为管理")
http.ListenAndServe(":9090", adminMux)
}
客户端
常用 API
http.Get(url): 发送简单的 GET 请求。http.Post(url, contentType, body): 发送 POST 请求。http.Client: 如果需要设置超时、Header 等高级操作,需要自定义 Client。
go
resp, err := http.Get("https://api.github.com")
if err != nil {
log.Fatal(err)
}
// 记得关闭 Body,防止内存泄漏
defer resp.Body.Close()
// 读取响应内容
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))