1 概述
net/http
是Go语言标准库中用于处理HTTP协议的核心组件,它提供了完整HTTP客户端和服务器实现。这个包让开发者能够快速构建高性能的Web服务,无需依赖第三方框架。
1.1 主要特性
- 内置高性能HTTP服务器:直接支持并发请求处理
- 简洁的API设计:易于上手和使用
- 完整的HTTP协议支持:支持HTTP/1.x和HTTP/2
- 强大的路由机制:灵活的路由匹配和处理
- 中间件支持:可扩展的中间件架构
2 HTTP服务器开发
2.1 基本服务器搭建
以下是创建一个最简单HTTP服务器的示例:
go
package main
import (
"fmt"
"net/http"
)
func main() {
// 注册处理函数
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, World!")
})
// 启动服务器
fmt.Println("Starting server on :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Printf("Error starting server: %v\n", err)
}
}
2.2 处理不同的HTTP方法
可以根据请求方法执行不同的逻辑:
go
func handler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
fmt.Fprint(w, "This is a GET request.")
case http.MethodPost:
fmt.Fprint(w, "This is a POST request.")
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
2.3 请求参数处理
查询参数(URL参数)
go
func queryHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
age := r.URL.Query().Get("age")
fmt.Fprintf(w, "Hello, %s! Age: %s", name, age)
}
表单数据
go
func formHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
err := r.ParseForm()
if err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
return
}
username := r.FormValue("username")
password := r.FormValue("password")
fmt.Fprintf(w, "Username: %s, Password: %s", username, password)
}
}
JSON请求体
go
func jsonHandler(w http.ResponseWriter, r *http.Request) {
type RequestData struct {
Name string `json:"name"`
Email string `json:"email"`
}
var data RequestData
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
fmt.Fprintf(w, "Name: %s, Email: %s", data.Name, data.Email)
}
2.4 路由管理
使用ServeMux进行路由管理
go
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", homeHandler)
mux.HandleFunc("/users", usersHandler)
mux.HandleFunc("/posts", postsHandler)
http.ListenAndServe(":8080", mux)
}
动态路由参数(需配合第三方路由库)
虽然标准库的ServeMux不支持动态路由参数,但可以结合正则表达式或使用第三方库实现。
3 HTTP客户端开发
3.1 发送GET请求
go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
resp, err := http.Get("https://jsonplaceholder.typicode.com/posts/1")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error reading body: %v\n", err)
return
}
fmt.Println(string(body))
}
3.2 发送POST请求
go
func main() {
data := []byte(`{"title": "foo", "body": "bar", "userId": 1}`)
resp, err := http.Post(
"https://jsonplaceholder.typicode.com/posts",
"application/json",
bytes.NewBuffer(data),
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
defer resp.Body.Close()
// 处理响应...
}
3.3 自定义请求
使用http.NewRequest
可以创建更复杂的请求:
go
func main() {
// 创建请求
data := []byte(`{"name": "Go"}`)
req, err := http.NewRequest("POST", "https://httpbin.org/post", bytes.NewBuffer(data))
if err != nil {
fmt.Printf("Error creating request: %v\n", err)
return
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer token123")
// 发送请求
client := &http.Client{
Timeout: time.Second * 10,
}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error sending request: %v\n", err)
return
}
defer resp.Body.Close()
// 处理响应...
}
3.4 客户端超时设置
go
func main() {
client := &http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Get("https://www.example.com")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
defer resp.Body.Close()
}
4 高级特性
4.1 中间件开发
中间件可以在处理HTTP请求前后执行特定逻辑:
go
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("Request: %s %s processed in %v",
r.Method, r.URL.Path, time.Since(start))
})
}
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token != "valid-token" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, World!")
})
// 应用中间件
handler := loggingMiddleware(authMiddleware(mux))
http.ListenAndServe(":8080", handler)
}
4.2 静态文件服务
go
func main() {
// 提供静态文件服务
fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Main page")
})
http.ListenAndServe(":8080", nil)
}
4.3 Cookie处理
go
func cookieHandler(w http.ResponseWriter, r *http.Request) {
// 读取Cookie
cookie, err := r.Cookie("session")
if err != nil {
// 创建新Cookie
cookie = &http.Cookie{
Name: "session",
Value: "session-id-123",
Path: "/",
HttpOnly: true,
}
http.SetCookie(w, cookie)
}
fmt.Fprintf(w, "Cookie value: %s", cookie.Value)
}
4.4 JSON响应
go
func jsonResponseHandler(w http.ResponseWriter, r *http.Request) {
type Response struct {
Status string `json:"status"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
response := Response{
Status: "success",
Message: "Data retrieved successfully",
Data: map[string]interface{}{
"id": 1,
"name": "John Doe",
},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
5 常见问题与解决方案
5.1 易错点及避免方法
易错点 | 问题描述 | 解决方案 |
---|---|---|
资源泄露 | 未关闭响应体 | 总是使用defer resp.Body.Close() |
路由冲突 | 路由匹配顺序错误 | 明确路由优先级,从具体到一般 |
阻塞操作 | 长时间运行的操作阻塞服务 | 使用goroutine处理耗时任务 |
内存泄漏 | 不当使用全局变量或缓存 | 合理管理资源生命周期 |
5.2 性能优化建议
- 连接复用 :使用
http.Client
的默认连接池 - 超时设置:为客户端和服务器设置合理的超时时间
- 并发处理:利用Go的并发特性处理请求
- 静态资源缓存:合理设置缓存头减少重复传输
5.3 安全最佳实践
go
func secureHeadersMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 设置安全相关的HTTP头
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("X-XSS-Protection", "1; mode=block")
w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
next.ServeHTTP(w, r)
})
}
6 实战案例:完整的API服务
以下是一个完整的用户管理API示例:
go
package main
import (
"encoding/json"
"log"
"net/http"
"strconv"
"time"
"github.com/gorilla/mux"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
var users = []User{
{ID: 1, Name: "Alice", Email: "alice@example.com"},
{ID: 2, Name: "Bob", Email: "bob@example.com"},
}
func getUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
func getUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
params := mux.Vars(r)
id, _ := strconv.Atoi(params["id"])
for _, user := range users {
if user.ID == id {
json.NewEncoder(w).Encode(user)
return
}
}
http.Error(w, "User not found", http.StatusNotFound)
}
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
user.ID = len(users) + 1
users = append(users, user)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
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 %v", r.Method, r.URL.Path, time.Since(start))
})
}
func main() {
router := mux.NewRouter()
// 路由定义
router.HandleFunc("/users", getUsers).Methods("GET")
router.HandleFunc("/users/{id}", getUser).Methods("GET")
router.HandleFunc("/users", createUser).Methods("POST")
// 应用中间件
router.Use(loggingMiddleware)
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", router))
}
7 总结
Go语言的net/http
包提供了一个强大而灵活的工具集,用于构建HTTP客户端和服务器应用程序。通过本文的介绍,您应该能够:
- 创建基本的HTTP服务器和客户端
- 处理各种类型的HTTP请求和响应
- 实现中间件以增强功能
- 避免常见的陷阱和错误
- 构建生产级别的Web服务
net/http
包的简洁设计和强大功能使得Go语言成为构建高性能Web服务的理想选择。随着对包的深入理解,您可以构建出既强大又易于维护的Web应用程序。