1. 为什么选择Go语言开发HTTP服务器?
Go语言自2009年由Google发布以来,凭借其简洁的语法、高效的并发模型和出色的性能,迅速成为后端开发的热门选择。根据2023年Stack Overflow开发者调查,Go语言在最受欢迎编程语言中排名前10,特别适合网络服务和分布式系统开发。
对于HTTP服务器开发,Go语言有几个显著优势:
- 标准库强大:net/http包提供了完整的HTTP服务器和客户端实现
- 并发模型优雅:goroutine和channel机制让高并发服务开发变得简单
- 部署方便:编译为单一可执行文件,无需复杂运行时环境
- 性能优异:接近C语言的执行效率,远高于Python、Ruby等脚本语言
2. 开发环境准备
2.1 Go语言安装
首先需要安装Go语言环境,最新稳定版本可以从官网下载:
- Windows用户:下载.msi安装包,双击运行
- macOS用户:使用
brew install go或下载.pkg安装包 - Linux用户:使用系统包管理器,如
sudo apt install golang
安装完成后,在终端运行go version验证安装是否成功。建议使用Go 1.20或更高版本。
2.2 开发工具配置
虽然可以使用任何文本编辑器开发Go程序,但推荐使用专业的IDE或编辑器插件:
- VS Code + Go插件(最轻量级的选择)
- Goland(JetBrains出品,功能最全)
- Vim/Emacs + 相应Go插件
创建项目目录结构:
bash复制mkdir my-http-server
cd my-http-server
go mod init github.com/yourname/my-http-server
3. 编写第一个HTTP服务器
3.1 基础服务器实现
创建一个main.go文件,输入以下代码:
go复制package main
import (
"fmt"
"net/http"
)
func main() {
// 注册路由处理函数
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
// 启动服务器
fmt.Println("Server starting on port 8080...")
http.ListenAndServe(":8080", nil)
}
这段代码做了以下几件事:
- 导入必要的标准库包
- 定义了一个根路径"/"的处理函数
- 在8080端口启动HTTP服务器
运行程序:
bash复制go run main.go
打开浏览器访问http://localhost:8080,应该能看到"Hello, World!"的响应。
3.2 代码解析
让我们深入理解这段代码的关键部分:
http.HandleFunc
- 用于注册路由和处理函数
- 第一个参数是URL路径模式
- 第二个参数是处理函数,类型为
func(http.ResponseWriter, *http.Request)
http.ResponseWriter
- 用于构建HTTP响应
- 实现了io.Writer接口,可以使用fmt.Fprintf等函数写入响应
- 可以设置状态码、头部等
http.Request
- 包含客户端请求的所有信息
- 方法、URL、头部、正文等
http.ListenAndServe
- 启动HTTP服务器
- 第一个参数是监听地址(":8080"表示所有网络接口的8080端口)
- 第二个参数通常是nil,表示使用默认的多路复用器
4. 扩展服务器功能
4.1 添加更多路由
实际应用中我们需要处理多个路由:
go复制http.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "About Page")
})
http.HandleFunc("/contact", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Contact Page")
})
4.2 处理不同HTTP方法
可以根据请求方法执行不同操作:
go复制http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
fmt.Fprintf(w, "GET request")
case "POST":
fmt.Fprintf(w, "POST request")
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
})
4.3 返回JSON响应
现代API通常返回JSON数据:
go复制http.HandleFunc("/data", func(w http.ResponseWriter, r *http.Request) {
data := map[string]interface{}{
"name": "Go Server",
"version": 1.0,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
})
5. 项目结构优化
5.1 分离处理函数
随着项目增长,应该将处理函数移到单独的包中:
创建handlers/handlers.go:
go复制package handlers
import (
"fmt"
"net/http"
)
func HomeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Home Page")
}
func AboutHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "About Page")
}
修改main.go:
go复制http.HandleFunc("/", handlers.HomeHandler)
http.HandleFunc("/about", handlers.AboutHandler)
5.2 使用结构体存储服务器配置
go复制type Server struct {
Addr string
}
func (s *Server) Start() error {
http.HandleFunc("/", handlers.HomeHandler)
return http.ListenAndServe(s.Addr, nil)
}
func main() {
server := &Server{Addr: ":8080"}
server.Start()
}
6. 添加中间件支持
中间件是处理HTTP请求/响应的强大工具:
6.1 日志中间件
go复制func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next(w, r)
duration := time.Since(start)
log.Printf("%s %s %v", r.Method, r.URL.Path, duration)
}
}
// 使用中间件
http.HandleFunc("/", loggingMiddleware(handlers.HomeHandler))
6.2 认证中间件
go复制func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token != "secret-token" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next(w, r)
}
}
7. 生产环境注意事项
7.1 错误处理
基础版本没有处理ListenAndServe的错误:
go复制if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatalf("Server failed: %v", err)
}
7.2 优雅关闭
支持优雅关闭,避免中断正在处理的请求:
go复制func main() {
server := &http.Server{
Addr: ":8080",
}
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatal("Server forced to shutdown:", err)
}
}
7.3 性能优化
- 使用
http.TimeoutHandler防止慢客户端占用连接 - 考虑使用
fasthttp替代标准库以获得更高性能 - 启用HTTP/2支持
8. 测试HTTP服务器
8.1 单元测试
go复制func TestHomeHandler(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
handlers.HomeHandler(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusOK {
t.Errorf("expected status OK, got %v", resp.StatusCode)
}
body, _ := io.ReadAll(resp.Body)
if string(body) != "Home Page" {
t.Errorf("expected 'Home Page', got %v", string(body))
}
}
8.2 集成测试
使用net/http/httptest包创建测试服务器:
go复制func TestServer(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(handlers.HomeHandler))
defer ts.Close()
res, err := http.Get(ts.URL)
if err != nil {
t.Fatal(err)
}
if res.StatusCode != http.StatusOK {
t.Errorf("expected status OK, got %v", res.StatusCode)
}
}
9. 部署选项
9.1 编译为可执行文件
bash复制go build -o server
./server
9.2 使用Docker容器
创建Dockerfile:
dockerfile复制FROM golang:1.20 as builder
WORKDIR /app
COPY . .
RUN go build -o server
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/server .
CMD ["./server"]
构建并运行:
bash复制docker build -t my-http-server .
docker run -p 8080:8080 my-http-server
9.3 云平台部署
- AWS: 使用EC2或ECS
- Google Cloud: 使用Compute Engine或Cloud Run
- Azure: 使用App Service或Container Instances
10. 性能监控
10.1 添加健康检查端点
go复制http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
10.2 使用pprof进行性能分析
go复制import _ "net/http/pprof"
func main() {
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
// 主服务器代码...
}
然后可以访问http://localhost:6060/debug/pprof/查看性能数据。
11. 安全最佳实践
11.1 防止SQL注入
即使这个简单服务器不涉及数据库,也要注意:
- 永远不要直接拼接SQL查询
- 使用参数化查询或ORM
11.2 设置安全头部
go复制func secureHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "deny")
w.Header().Set("X-XSS-Protection", "1; mode=block")
next.ServeHTTP(w, r)
})
}
11.3 限制请求大小
go复制http.Handle("/upload", http.MaxBytesHandler(uploadHandler, 10<<20)) // 10MB限制
12. 进阶主题
12.1 使用第三方路由库
标准库的路由功能有限,可以考虑:
- Gorilla Mux
- Chi
- Echo
- Gin
以Chi为例:
go复制r := chi.NewRouter()
r.Get("/", handlers.HomeHandler)
r.Get("/about", handlers.AboutHandler)
http.ListenAndServe(":8080", r)
12.2 WebSocket支持
go复制http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
for {
messageType, p, err := conn.ReadMessage()
if err != nil {
return
}
if err := conn.WriteMessage(messageType, p); err != nil {
return
}
}
})
12.3 GRPC集成
Go也适合开发GRPC服务,可以与HTTP服务共存:
go复制grpcServer := grpc.NewServer()
pb.RegisterYourServiceServer(grpcServer, &server{})
mux := http.NewServeMux()
mux.HandleFunc("/", homeHandler)
http.ListenAndServe(":8080", h2c.NewHandler(mux, &http2.Server{}))
13. 实际项目建议
在真实项目中,建议考虑以下方面:
- 配置管理:使用环境变量或配置文件
- 结构化日志:使用zap或logrus等日志库
- 指标监控:集成Prometheus客户端
- 链路追踪:添加OpenTelemetry支持
- API文档:使用Swagger或OpenAPI
一个更完整的main.go可能如下:
go复制func main() {
// 初始化配置
cfg := config.Load()
// 设置日志
logger := logrus.New()
logger.SetFormatter(&logrus.JSONFormatter{})
// 创建路由器
r := chi.NewRouter()
// 添加中间件
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
// 注册路由
r.Get("/", handlers.HomeHandler)
r.Get("/health", handlers.HealthHandler)
// 启动服务器
server := &http.Server{
Addr: cfg.Address,
Handler: r,
ReadTimeout: 10 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 60 * time.Second,
}
logger.Infof("Starting server on %s", cfg.Address)
if err := server.ListenAndServe(); err != nil {
logger.Fatalf("Server failed: %v", err)
}
}
14. 学习资源推荐
要深入学习Go Web开发,可以参考:
- 官方文档:https://golang.org/pkg/net/http/
- 《Go Web编程》:郑兆雄著
- Awesome Go:GitHub上的Go资源集合
- Go by Example:https://gobyexample.com/
- Gophercises:实用的Go练习项目
15. 常见问题解答
Q: 为什么我的服务器响应很慢?
A: 可能原因:1) 处理函数中有阻塞操作 2) 没有设置超时 3) 系统资源不足。建议添加超时设置和性能监控。
Q: 如何处理HTTPS请求?
A: 使用ListenAndServeTLS代替ListenAndServe,需要提供证书和密钥文件。
Q: 如何实现文件上传?
A: 使用r.ParseMultipartForm解析表单,然后通过r.FormFile获取上传的文件。
Q: 为什么我的路由不工作?
A: 检查路由注册顺序(更具体的路由应该先注册),确保路径匹配正确,注意结尾斜杠的处理。
Q: 如何获取查询参数?
A: 使用r.URL.Query().Get("param")获取URL查询参数,或r.FormValue("param")获取表单值。
Q: 推荐的项目结构是怎样的?
A: 常见结构:
code复制/project
/cmd
/server
main.go
/internal
/handlers
/models
/pkg
/configs
/scripts
go.mod
go.sum
16. 性能调优技巧
- 连接池:重用HTTP客户端,设置合理的连接池大小
- 缓冲写入:对大量响应使用bufio.Writer
- 减少分配:重用对象,避免频繁内存分配
- 并行处理:对独立任务使用goroutine
- 压缩响应:对文本响应启用gzip压缩
示例压缩中间件:
go复制func gzipMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
gz := gzip.NewWriter(w)
defer gz.Close()
w.Header().Set("Content-Encoding", "gzip")
next.ServeHTTP(gzipResponseWriter{Writer: gz, ResponseWriter: w}, r)
} else {
next.ServeHTTP(w, r)
}
})
}
17. 错误处理模式
良好的错误处理能提高服务可靠性:
go复制func apiHandler(w http.ResponseWriter, r *http.Request) {
data, err := getData()
if err != nil {
handleError(w, err)
return
}
if err := json.NewEncoder(w).Encode(data); err != nil {
handleError(w, err)
return
}
}
func handleError(w http.ResponseWriter, err error) {
switch e := err.(type) {
case *ValidationError:
http.Error(w, e.Error(), http.StatusBadRequest)
case *NotFoundError:
http.Error(w, e.Error(), http.StatusNotFound)
default:
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}
18. 上下文使用
Go的context包对HTTP服务非常重要:
go复制func slowHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
select {
case <-time.After(5 * time.Second):
fmt.Fprintf(w, "Done")
case <-ctx.Done():
err := ctx.Err()
log.Printf("Request canceled: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
19. 测试覆盖率提升
确保测试覆盖主要场景:
- 正常路径测试:验证成功情况
- 错误路径测试:模拟各种错误条件
- 边界条件测试:测试极限值
- 性能测试:使用
go test -bench - 集成测试:测试组件交互
示例表驱动测试:
go复制func TestHandler(t *testing.T) {
tests := []struct {
name string
url string
wantCode int
wantBody string
}{
{"home", "/", 200, "Home Page"},
{"not found", "/notfound", 404, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := httptest.NewRequest("GET", tt.url, nil)
w := httptest.NewRecorder()
handler(w, req)
resp := w.Result()
if resp.StatusCode != tt.wantCode {
t.Errorf("got status %d, want %d", resp.StatusCode, tt.wantCode)
}
body, _ := io.ReadAll(resp.Body)
if !strings.Contains(string(body), tt.wantBody) {
t.Errorf("unexpected body: %s", body)
}
})
}
}
20. 持续集成与部署
设置CI/CD流程确保代码质量:
.github/workflows/go.yml示例:
yaml复制name: Go
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.20'
- run: go test -v -coverprofile=coverage.out ./...
- run: go vet ./...
- run: go fmt ./...
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- run: go build -o server
- uses: actions/upload-artifact@v2
with:
name: server
path: server
21. 实际项目案例
假设我们要开发一个简单的TODO API:
go复制// models/todo.go
type Todo struct {
ID string `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
CreatedAt time.Time `json:"created_at"`
}
// handlers/todo.go
func CreateTodo(w http.ResponseWriter, r *http.Request) {
var todo models.Todo
if err := json.NewDecoder(r.Body).Decode(&todo); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
todo.ID = uuid.New().String()
todo.CreatedAt = time.Now()
// 保存到数据库...
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(todo)
}
// main.go
r := chi.NewRouter()
r.Route("/todos", func(r chi.Router) {
r.Get("/", handlers.ListTodos)
r.Post("/", handlers.CreateTodo)
r.Get("/{id}", handlers.GetTodo)
r.Put("/{id}", handlers.UpdateTodo)
r.Delete("/{id}", handlers.DeleteTodo)
})
22. 调试技巧
- 使用Delve调试器:
bash复制dlv debug ./main.go
- 打印请求信息:
go复制func dumpRequest(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, _ := httputil.DumpRequest(r, true)
log.Println(string(data))
next.ServeHTTP(w, r)
})
}
- 记录慢请求:
go复制func logSlowRequests(next http.Handler, threshold time.Duration) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
duration := time.Since(start)
if duration > threshold {
log.Printf("Slow request: %s %s took %v", r.Method, r.URL.Path, duration)
}
})
}
23. 依赖管理
使用Go Modules管理依赖:
初始化:
bash复制go mod init github.com/yourname/project
添加依赖:
bash复制go get github.com/gorilla/mux
更新依赖:
bash复制go get -u
go mod tidy
24. 跨域支持
处理跨域请求:
go复制func enableCORS(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, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
25. 版本控制最佳实践
- API版本控制:
go复制r.Route("/v1", func(r chi.Router) {
r.Get("/users", v1.ListUsers)
})
r.Route("/v2", func(r chi.Router) {
r.Get("/users", v2.ListUsers)
})
- 代码版本控制:
- 使用语义化版本控制(SemVer)
- 保持提交信息清晰
- 使用特性分支工作流
26. 文档生成
使用swaggo等工具生成API文档:
安装:
bash复制go get -u github.com/swaggo/swag/cmd/swag
添加注释:
go复制// @Summary 获取TODO列表
// @Description 获取所有TODO项
// @Tags todos
// @Accept json
// @Produce json
// @Success 200 {array} models.Todo
// @Router /todos [get]
func ListTodos(w http.ResponseWriter, r *http.Request) {
// 处理代码...
}
生成文档:
bash复制swag init
27. 负载测试
使用vegeta进行负载测试:
bash复制echo "GET http://localhost:8080" | vegeta attack -duration=10s -rate=100 | vegeta report
关键指标:
- 请求速率(QPS)
- 延迟分布
- 错误率
- 吞吐量
28. 日志聚合
在生产环境中,建议使用:
- ELK Stack (Elasticsearch, Logstash, Kibana)
- Fluentd
- Loki + Grafana
Go日志示例:
go复制logger := logrus.New()
logger.SetFormatter(&logrus.JSONFormatter{})
logger.WithFields(logrus.Fields{
"url": r.URL.Path,
"method": r.Method,
}).Info("request received")
29. 配置管理
使用viper管理配置:
go复制type Config struct {
Port int `mapstructure:"PORT"`
DatabaseURL string `mapstructure:"DATABASE_URL"`
}
func LoadConfig() (*Config, error) {
var cfg Config
viper.SetDefault("PORT", 8080)
viper.AutomaticEnv()
if err := viper.Unmarshal(&cfg); err != nil {
return nil, err
}
return &cfg, nil
}
30. 容器化最佳实践
优化Docker镜像:
- 使用多阶段构建减小镜像大小
- 使用非root用户运行
- 设置合理的资源限制
- 添加健康检查
- 使用.dockerignore文件
优化后的Dockerfile:
dockerfile复制# 构建阶段
FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -ldflags="-s -w" -o server
# 运行阶段
FROM alpine:latest
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder --chown=appuser:appgroup /app/server .
USER appuser
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
CMD ["./server"]
31. 零停机部署策略
- 蓝绿部署:准备两套环境,切换流量
- 滚动更新:逐步替换实例
- 金丝雀发布:先向小部分用户发布
使用Kubernetes实现滚动更新:
yaml复制spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
32. 限速与配额
防止滥用API:
go复制rateLimiter := tollbooth.NewLimiter(100, nil) // 100请求/秒
http.Handle("/", tollbooth.LimitFuncHandler(rateLimiter, homeHandler))
更复杂的可以使用:
- Redis + Lua脚本实现分布式限流
- 漏桶/令牌桶算法
33. 缓存策略
常见缓存位置:
- 客户端缓存 (Cache-Control头部)
- 反向代理缓存 (Nginx, Varnish)
- 应用内存缓存 (sync.Map, bigcache)
- 分布式缓存 (Redis, Memcached)
示例内存缓存:
go复制var cache = struct {
sync.RWMutex
items map[string]interface{}
}{items: make(map[string]interface{})}
func getFromCache(key string) (interface{}, bool) {
cache.RLock()
defer cache.RUnlock()
val, ok := cache.items[key]
return val, ok
}
34. 数据库集成
集成PostgreSQL示例:
go复制import "github.com/jmoiron/sqlx"
func main() {
db, err := sqlx.Connect("postgres", "user=postgres dbname=mydb sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 在handler中使用db
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
var users []User
err := db.Select(&users, "SELECT * FROM users")
// 处理错误和响应...
})
}
35. 认证与授权
JWT认证示例:
go复制func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
if tokenString == "" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte("secret"), nil
})
if err != nil || !token.Valid {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
36. 微服务通信
服务间通信方式:
- REST API
- GRPC
- 消息队列 (NATS, Kafka)
- 事件驱动 (EventBridge)
GRPC客户端示例:
go复制conn, err := grpc.Dial("user-service:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
client := pb.NewUserServiceClient(conn)
resp, err := client.GetUser(context.Background(), &pb.GetUserRequest{Id: "123"})
37. 可观测性
三大支柱:
- 指标:Prometheus客户端
- 日志:结构化日志
- 追踪:OpenTelemetry
Prometheus示例:
go复制import "github.com/prometheus/client_golang/prometheus/promhttp"
func main() {
http.Handle("/metrics", promhttp.Handler())
// 其他路由...
}
38. 混沌工程
测试系统弹性:
- 注入延迟
- 模拟失败
- 杀死进程
- 网络分区
使用chaos-mesh或自定义中间件:
go复制func chaosMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if rand.Intn(100) < 5 { // 5%失败率
http.Error(w, "Chaos engineering", http.StatusInternalServerError)
return
}
next.ServeHTTP(w, r)
})
}
39. 国际化支持
处理多语言:
go复制var messages = map[string]map[string]string{
"en": {
"welcome": "Welcome",
},
"zh": {
"welcome": "欢迎",
},
}
func getMessage(lang, key string) string {
if msgs, ok := messages[lang]; ok {
if msg, ok := msgs[key]; ok {
return msg
}
}
return key
}
40. WebAssembly集成
Go也可以编译为WASM:
go复制// main_wasm.go
package main
import "syscall/js"
func main() {
js.Global().Set("goAdd", js.FuncOf(add))
select {} // 保持运行
}
func add(this js.Value, args []js.Value) interface{} {
return args[0].Int() + args[1].Int()
}
构建:
bash复制GOOS=js GOARCH=wasm go build -o main.wasm
41. 自动化API测试
使用httpexpect:
go复制func TestAPI(t *testing.T) {
handler := setupServer()
e := httpexpect.New(t, handler)
e.GET("/todos").
Expect().
Status(http.StatusOK).
JSON().Array().Empty()
e.POST("/todos").
WithJSON(map[string]interface{}{"title": "test"}).
Expect().
Status(http.StatusCreated)
}
42. 前端集成
服务静态文件:
go复制fs := http.FileServer(http.Dir("./static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
API代理(开发时):
go复制func proxyToFrontendDevServer(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/api") {
next.ServeHTTP(w, r)
} else {
proxy := httputil.NewSingleHostReverseProxy("http://localhost:3000")
proxy.ServeHTTP(w, r)
}
})
}
43. 长期运行任务
使用工作队列:
go复制func startWorker(queue chan Job) {
for job := range queue {
go processJob(job)
}
}
func processJob(job Job) {
// 长时间运行的任务...
}
func main() {
jobQueue := make(chan Job, 100)
go startWorker(jobQueue)
http.HandleFunc("/job", func(w http.ResponseWriter, r *http.Request) {
job := Job{Data: r.FormValue("data")}
jobQueue <- job
w.WriteHeader(http.StatusAccepted)
})
}
44. 文件处理
上传文件示例:
go复制http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(10 << 20) // 10MB限制
file, handler, err := r.FormFile("file")
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer file.Close()
dst, err := os.Create(handler.Filename)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer dst.Close()
if _, err := io.Copy(dst, file); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "File uploaded successfully")
})
45. 模板渲染
使用html/template:
go复制func renderTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
t, err := template.ParseFiles("templates/" + tmpl + ".html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
t.Execute(w, data)
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := struct {
Title string
}{
Title: "Home Page",
}
renderTemplate(w, "home", data)
})
46. 命令行接口
添加CLI支持:
go复制import "github.com/spf13/cobra"
func main() {
var rootCmd = &cobra.Command{
Use: "server",
}
var serveCmd = &cobra.Command{
Use: "serve",
Run: func(cmd *cobra.Command, args []string) {
startServer()
},
}
rootCmd.AddCommand(serveCmd)
rootCmd.Execute()
}
47. 代码生成
使用go:generate:
go复制//go:generate stringer -type=Status
type Status int
const (
Pending Status = iota
Completed
Failed
)
运行:
bash复制