Go Web 开发与微服务

00:00
2 min Advanced 2026/6/14

net/http 标准库、Gin/Echo/Fiber 框架、中间件模式、RESTful API、gRPC、数据库操作、项目结构与容器化部署。

1. net/http 标准库

1.1 基础 HTTP 服务器

func main() {
    // 简单路由
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, World!")
    })

    http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodGet:
            listUsers(w, r)
        case http.MethodPost:
            createUser(w, r)
        default:
            w.WriteHeader(http.StatusMethodNotAllowed)
        }
    })

    log.Fatal(http.ListenAndServe(":8080", nil))
}

1.2 Go 1.22+ 增强路由

mux := http.NewServeMux()

// 方法 + 路径模式
mux.HandleFunc("GET /users", listUsers)
mux.HandleFunc("POST /users", createUser)
mux.HandleFunc("GET /users/{id}", getUser)
mux.HandleFunc("PUT /users/{id}", updateUser)
mux.HandleFunc("DELETE /users/{id}", deleteUser)

// 路径参数
func getUser(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id")
    json.NewEncoder(w).Encode(map[string]string{
        "id":   id,
        "name": "User " + id,
    })
}

// 尾部斜杠匹配
mux.HandleFunc("GET /files/{path...}", getFiles) // 匹配 /files/a/b/c

log.Fatal(http.ListenAndServe(":8080", mux))

1.3 自定义 Handler

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

type APIHandler struct {
    users map[string]*User
}

func (h *APIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    // 路由逻辑...
}

// 使用
handler := &APIHandler{users: make(map[string]*User)}
http.ListenAndServe(":8080", handler)

1.4 HTTP 中间件

// 中间件函数签名
type Middleware func(http.Handler) http.Handler

// 日志中间件
func Logging(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 Recovery(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        defer func() {
            if err := recover(); err != nil {
                log.Printf("panic: %v\n%s", err, debug.Stack())
                http.Error(w, "Internal Server Error", 500)
            }
        }()
        next.ServeHTTP(w, r)
    })
}

// CORS 中间件
func CORS(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 == "OPTIONS" {
            w.WriteHeader(204)
            return
        }
        next.ServeHTTP(w, r)
    })
}

// 链式中间件
func Chain(h http.Handler, mws ...Middleware) http.Handler {
    for i := len(mws) - 1; i >= 0; i-- {
        h = mws[i](h)
    }
    return h
}

// 使用
mux := http.NewServeMux()
mux.HandleFunc("/", handler)
chain := Chain(mux, Logging, Recovery, CORS)
http.ListenAndServe(":8080", chain)

2. Gin 框架

2.1 基础用法

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default() // 包含 Logger 和 Recovery 中间件

    // 路由
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{"message": "pong"})
    })

    // 路径参数
    r.GET("/users/:id", func(c *gin.Context) {
        id := c.Param("id")
        c.JSON(200, gin.H{"id": id})
    })

    // 查询参数
    r.GET("/search", func(c *gin.Context) {
        q := c.Query("q")
        page := c.DefaultQuery("page", "1")
        c.JSON(200, gin.H{"query": q, "page": page})
    })

    // 请求体绑定
    r.POST("/users", func(c *gin.Context) {
        var user User
        if err := c.ShouldBindJSON(&user); err != nil {
            c.JSON(400, gin.H{"error": err.Error()})
            return
        }
        c.JSON(201, user)
    })

    r.Run(":8080")
}

2.2 路由分组

func main() {
    r := gin.Default()

    // API 版本分组
    v1 := r.Group("/api/v1")
    {
        v1.GET("/users", listUsers)
        v1.POST("/users", createUser)
        v1.GET("/users/:id", getUser)
    }

    v2 := r.Group("/api/v2")
    {
        v2.GET("/users", listUsersV2)
    }

    // 中间件分组
    auth := r.Group("/admin", AuthMiddleware())
    {
        auth.GET("/dashboard", dashboard)
        auth.GET("/settings", settings)
    }

    r.Run()
}

2.3 Gin 中间件

// 自定义中间件
func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")
        if token == "" {
            c.AbortWithStatusJSON(401, gin.H{"error": "unauthorized"})
            return
        }
        // 验证 token...
        userID, err := validateToken(token)
        if err != nil {
            c.AbortWithStatusJSON(401, gin.H{"error": "invalid token"})
            return
        }
        c.Set("userID", userID)
        c.Next()
    }
}

// 使用
r.Use(AuthMiddleware())

3. Echo 框架

import "github.com/labstack/echo/v4"

func main() {
    e := echo.New()

    // 中间件
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
    e.Use(middleware.CORS())

    // 路由
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })

    e.GET("/users/:id", func(c echo.Context) error {
        id := c.Param("id")
        return c.JSON(200, map[string]string{"id": id})
    })

    // 请求绑定
    e.POST("/users", func(c echo.Context) error {
        u := new(User)
        if err := c.Bind(u); err != nil {
            return echo.NewHTTPError(400, err.Error())
        }
        if err := c.Validate(u); err != nil {
            return echo.NewHTTPError(400, err.Error())
        }
        return c.JSON(201, u)
    })

    e.Logger.Fatal(e.Start(":8080"))
}

4. RESTful API 设计

4.1 标准 RESTful 路由

GET    /api/v1/users          — 列表
POST   /api/v1/users          — 创建
GET    /api/v1/users/:id      — 详情
PUT    /api/v1/users/:id      — 全量更新
PATCH  /api/v1/users/:id      — 部分更新
DELETE /api/v1/users/:id      — 删除

4.2 统一响应格式

type Response struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Data    any    `json:"data,omitempty"`
}

type PageResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Data    any    `json:"data"`
    Total   int64  `json:"total"`
    Page    int    `json:"page"`
    Size    int    `json:"size"`
}

func Success(c *gin.Context, data any) {
    c.JSON(200, Response{Code: 0, Message: "success", Data: data})
}

func Error(c *gin.Context, status int, msg string) {
    c.JSON(status, Response{Code: status, Message: msg})
}

4.3 请求验证

type CreateUserReq struct {
    Name  string `json:"name" binding:"required,min=2,max=50"`
    Email string `json:"email" binding:"required,email"`
    Age   int    `json:"age" binding:"required,gte=0,lte=150"`
}

func createUser(c *gin.Context) {
    var req CreateUserReq
    if err := c.ShouldBindJSON(&req); err != nil {
        Error(c, 400, err.Error())
        return
    }
    // 处理请求...
    Success(c, req)
}

5. gRPC

5.1 定义 Protobuf

// api/user.proto
syntax = "proto3";
package api;

option go_package = "github.com/example/api";

service UserService {
    rpc GetUser(GetUserRequest) returns (GetUserResponse);
    rpc ListUsers(ListUsersRequest) returns (stream User);
    rpc CreateUser(CreateUserRequest) returns (CreateUserResponse);
}

message GetUserRequest {
    string id = 1;
}

message GetUserResponse {
    User user = 1;
}

message User {
    string id = 1;
    string name = 2;
    string email = 3;
}

message ListUsersRequest {
    int32 page = 1;
    int32 size = 2;
}

message CreateUserRequest {
    string name = 1;
    string email = 2;
}

message CreateUserResponse {
    User user = 1;
}

5.2 服务端实现

type server struct {
    pb.UnimplementedUserServiceServer
}

func (s *server) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) {
    user, err := db.GetUser(ctx, req.Id)
    if err != nil {
        return nil, status.Errorf(codes.NotFound, "user %s not found", req.Id)
    }
    return &pb.GetUserResponse{User: &pb.User{
        Id:    user.ID,
        Name:  user.Name,
        Email: user.Email,
    }}, nil
}

func main() {
    lis, _ := net.Listen("tcp", ":50051")
    s := grpc.NewServer(
        grpc.UnaryInterceptor(interceptor.Logging),
    )
    pb.RegisterUserServiceServer(s, &server{})
    log.Fatal(s.Serve(lis))
}

5.3 客户端调用

conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
defer conn.Close()

client := pb.NewUserServiceClient(conn)

resp, err := client.GetUser(ctx, &pb.GetUserRequest{Id: "42"})
if err != nil {
    st, ok := status.FromError(err)
    fmt.Println(st.Code(), st.Message())
}

6. 数据库操作

6.1 database/sql

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/dbname?parseTime=true")
if err != nil {
    log.Fatal(err)
}
defer db.Close()

// 配置连接池
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)

// 查询单行
var user User
err = db.QueryRowContext(ctx, "SELECT id, name, email FROM users WHERE id = ?", id).
    Scan(&user.ID, &user.Name, &user.Email)

// 查询多行
rows, err := db.QueryContext(ctx, "SELECT id, name FROM users LIMIT ?", limit)
defer rows.Close()
for rows.Next() {
    var u User
    rows.Scan(&u.ID, &u.Name)
}

// 插入
result, err := db.ExecContext(ctx,
    "INSERT INTO users (name, email) VALUES (?, ?)", name, email)
id, _ := result.LastInsertId()

// 更新
result, err := db.ExecContext(ctx,
    "UPDATE users SET name = ? WHERE id = ?", name, id)
affected, _ := result.RowsAffected()

// 事务
tx, _ := db.BeginTx(ctx, nil)
_, err = tx.ExecContext(ctx, "UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, fromID)
if err != nil {
    tx.Rollback()
    return err
}
_, err = tx.ExecContext(ctx, "UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, toID)
if err != nil {
    tx.Rollback()
    return err
}
tx.Commit()

6.2 GORM

import "gorm.io/gorm"

type User struct {
    ID        uint           `gorm:"primaryKey" json:"id"`
    Name      string         `gorm:"size:100;not null" json:"name"`
    Email     string         `gorm:"size:255;uniqueIndex" json:"email"`
    Age       int            `json:"age"`
    CreatedAt time.Time      `json:"created_at"`
    UpdatedAt time.Time      `json:"updated_at"`
    DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}

// 连接
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

// 自动迁移
db.AutoMigrate(&User{})

// CRUD
db.Create(&User{Name: "Alice", Email: "alice@example.com", Age: 30})

var user User
db.First(&user, 1)                           // 按主键
db.First(&user, "email = ?", "alice@ex.com") // 条件查询

db.Model(&user).Update("age", 31)
db.Model(&user).Updates(User{Name: "Alice2", Age: 31})
db.Delete(&user) // 软删除

// 查询构建器
var users []User
db.Where("age > ?", 20).Order("name").Limit(10).Find(&users)
db.Select("name, age").Where("name LIKE ?", "%ali%").Find(&users)

// 预加载关联
db.Preload("Orders").Find(&users)

// 分页
func Paginate(page, size int) func(db *gorm.DB) *gorm.DB {
    return func(db *gorm.DB) *gorm.DB {
        offset := (page - 1) * size
        return db.Offset(offset).Limit(size)
    }
}

var users []User
var total int64
db.Model(&User{}).Count(&total)
db.Scopes(Paginate(1, 10)).Find(&users)

7. 项目结构

7.1 标准项目布局

myapp/
├── cmd/
│   └── server/
│       └── main.go          # 入口
├── internal/
│   ├── handler/             # HTTP 处理器
│   │   └── user.go
│   ├── service/             # 业务逻辑
│   │   └── user.go
│   ├── repository/          # 数据访问
│   │   └── user.go
│   ├── model/               # 数据模型
│   │   └── user.go
│   └── middleware/           # 中间件
│       └── auth.go
├── pkg/                     # 可复用公共库
│   ├── response/
│   └── validator/
├── api/                     # API 定义
│   └── proto/
├── configs/                 # 配置文件
│   └── config.yaml
├── migrations/              # 数据库迁移
├── scripts/                 # 脚本
├── go.mod
├── go.sum
├── Makefile
└── Dockerfile

7.2 分层架构

// handler 层 — 处理 HTTP 请求/响应
type UserHandler struct {
    svc *UserService
}

func (h *UserHandler) Get(c *gin.Context) {
    id := c.Param("id")
    user, err := h.svc.Get(c.Request.Context(), id)
    if err != nil {
        Error(c, 500, err.Error())
        return
    }
    Success(c, user)
}

// service 层 — 业务逻辑
type UserService struct {
    repo UserRepository
}

func (s *UserService) Get(ctx context.Context, id string) (*User, error) {
    return s.repo.FindByID(ctx, id)
}

// repository 层 — 数据访问
type UserRepository interface {
    FindByID(ctx context.Context, id string) (*User, error)
    Create(ctx context.Context, user *User) error
}

// 依赖注入
func main() {
    db, _ := gorm.Open(mysql.Open(dsn))
    repo := NewGormUserRepository(db)
    svc := NewUserService(repo)
    handler := NewUserHandler(svc)

    r := gin.Default()
    r.GET("/users/:id", handler.Get)
    r.Run()
}

8. 配置管理

// 使用 Viper 管理配置
import "github.com/spf13/viper"

type Config struct {
    Server   ServerConfig   `mapstructure:"server"`
    Database DatabaseConfig `mapstructure:"database"`
    Redis    RedisConfig    `mapstructure:"redis"`
}

type ServerConfig struct {
    Port int    `mapstructure:"port"`
    Mode string `mapstructure:"mode"`
}

type DatabaseConfig struct {
    DSN             string `mapstructure:"dsn"`
    MaxOpenConns    int    `mapstructure:"max_open_conns"`
    MaxIdleConns    int    `mapstructure:"max_idle_conns"`
    ConnMaxLifetime int    `mapstructure:"conn_max_lifetime"`
}

func LoadConfig() (*Config, error) {
    viper.SetConfigName("config")
    viper.SetConfigType("yaml")
    viper.AddConfigPath("./configs")
    viper.AutomaticEnv() // 读取环境变量

    if err := viper.ReadInConfig(); err != nil {
        return nil, err
    }

    var cfg Config
    if err := viper.Unmarshal(&cfg); err != nil {
        return nil, err
    }
    return &cfg, nil
}

9. 部署与容器化

9.1 Dockerfile(多阶段构建)

# 构建阶段
FROM golang:1.24-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server ./cmd/server

# 运行阶段
FROM alpine:3.19

RUN apk --no-cache add ca-certificates tzdata
ENV TZ=Asia/Shanghai

WORKDIR /app
COPY --from=builder /app/server .
COPY --from=builder /app/configs ./configs

EXPOSE 8080
CMD ["./server"]

9.2 Docker Compose

version: '3.8'
services:
  app:
    build: .
    ports:
      - '8080:8080'
    environment:
      - DB_DSN=user:pass@tcp(mysql:3306)/app?parseTime=true
      - REDIS_ADDR=redis:6379
    depends_on:
      - mysql
      - redis

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: app
    ports:
      - '3306:3306'
    volumes:
      - mysql_data:/var/lib/mysql

  redis:
    image: redis:7-alpine
    ports:
      - '6379:6379'

volumes:
  mysql_data:

9.3 Kubernetes 部署

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myapp:latest
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /readyz
              port: 8080
            initialDelaySeconds: 3
            periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
  ports:
    - port: 80
      targetPort: 8080
  type: LoadBalancer

9.4 健康检查

r := gin.Default()

r.GET("/healthz", func(c *gin.Context) {
    // 检查数据库连接
    if err := db.Ping(); err != nil {
        c.JSON(503, gin.H{"status": "unhealthy", "db": "down"})
        return
    }
    c.JSON(200, gin.H{"status": "healthy"})
})

r.GET("/readyz", func(c *gin.Context) {
    c.JSON(200, gin.H{"ready": true})
})

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式