Go资深架构师是怎么实现分页接口的?

1 阅读11分钟

一个分页功能,三代工程师,三种境界


📖 故事背景

时间:2026 年春
公司:某快速成长的 Startup
项目:用户管理系统
需求:实现用户列表分页接口

┌─────────────────────────────────────────────────────────┐
│  📋 需求文档                                             │
│  ─────────────────────────────────────────────────────  │
│  接口:GET /api/users                                   │
│  参数:page(页码), page_size(每页条数)                   │
│  返回:用户列表 + 分页信息                               │
│  要求:快速上线,支持后续扩展                            │
└─────────────────────────────────────────────────────────┘

这个故事,关于成长,关于技术,关于选择。


👶 第一阶段:初级工程师的实现

人物介绍

小明,入职 3 个月,第一份 Go 工作
特点:能跑就行,快速交付
口头禅:"先上线,后面再优化"

代码实现 (user_handler.go)

package handler

import (
	"net/http"
	"strconv"

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

// User 用户模型
type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

// GetUserList 用户列表接口
func GetUserList(c *gin.Context) {
	// 1. 获取分页参数
	pageStr := c.DefaultQuery("page", "1")
	pageSizeStr := c.DefaultQuery("page_size", "10")

	page, _ := strconv.Atoi(pageStr)
	pageSize, _ := strconv.Atoi(pageSizeStr)

	// 2. 计算 offset
	offset := (page - 1) * pageSize

	// 3. 查询数据库(模拟)
	users := mockUsers(offset, pageSize)
	total := 100

	// 4. 返回结果
	c.JSON(http.StatusOK, gin.H{
		"page":      page,
		"page_size": pageSize,
		"total":     total,
		"users":     users,
	})
}

// 模拟用户数据
func mockUsers(offset, limit int) []User {
	var users []User
	for i := 0; i < limit; i++ {
		id := offset + i + 1
		users = append(users, User{
			ID:   id,
			Name: "User-" + strconv.Itoa(id),
		})
	}
	return users
}

路由注册 (main.go)

package main

import (
	"github.com/gin-gonic/gin"
	"yourapp/handler"
)

func main() {
	r := gin.Default()
	
	// 直接注册 handler
	r.GET("/api/users", handler.GetUserList)
	
	r.Run(":8080")
}

小明的内心独白

"搞定!只用了 30 分钟!参数获取、计算、返回,一气呵成。 老板说要快速上线,我这个实现绝对够快。 至于错误处理?应该没人会传负数吧... 至于代码复用?等其他接口需要时再说吧。"

代码评审现场

┌─────────────────────────────────────────────────────────┐
│  👨‍💼 Tech Lead 的评论                                    │
│  ─────────────────────────────────────────────────────  │
│  ✅ 功能正常,可以上线                                   │
│  ⚠️  错误被忽略了(strconv.Atoi 的 error)               │
│  ⚠️  没有参数校验(page=-1 会怎样?)                    │
│  ⚠️  每个接口都要复制这套逻辑?                          │
│  ⚠️  如果明天要加排序呢?                                │
│  ─────────────────────────────────────────────────────  │
│  结论:先上线,下个 sprint 重构                          │
└─────────────────────────────────────────────────────────┘

初级方案的问题清单

问题严重性后果
错误静默忽略🔴 高分页参数错误时返回错误数据
无参数校验🔴 高page=-1 导致 offset 为负
代码重复🟡 中每个接口都要写一遍分页逻辑
无扩展性🟡 中加排序需要改所有接口
测试困难🟡 中逻辑耦合,难以单元测试

上线后的问题

# 问题 1:恶意请求
curl "http://localhost:8080/api/users?page=-1"
# 返回:offset = -20,数据库报错

# 问题 2:爬虫攻击
curl "http://localhost:8080/api/users?page_size=10000"
# 返回:一次性拉取 10000 条,内存爆炸

# 问题 3:新需求来了
# 产品:需要支持按创建时间排序
# 小明:... 我得改 20 个接口

👨‍ 第二阶段:高级工程师的实现

人物介绍

小红,入职 2 年,带过 2 个项目
特点:注重代码质量,追求复用
口头禅:"这个可以抽象一下"

重构思路

┌─────────────────────────────────────────────────────────┐
│  小红的重构计划                                          │
│  ─────────────────────────────────────────────────────  │
│  1. 提取分页中间件 → 所有接口复用                        │
│  2. 统一参数校验   → 防止非法输入                        │
│  3. 统一响应格式   → 前端对接更方便                      │
│  4. 添加单元测试   → 保证质量                            │
└─────────────────────────────────────────────────────────┘

代码实现

1. 分页中间件 (middleware/pagination.go)

package middleware

import (
	"net/http"
	"strconv"

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

const (
	DefaultPage     = 1
	DefaultPageSize = 20
	MaxPageSize     = 100
)

// Pagination 分页信息
type Pagination struct {
	Page     int `json:"page"`
	PageSize int `json:"page_size"`
	Offset   int `json:"-"`
}

// PaginationMiddleware 分页中间件
func PaginationMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 1. 获取并校验 page
		page := DefaultPage
		if p := c.Query("page"); p != "" {
			if val, err := strconv.Atoi(p); err == nil && val > 0 {
				page = val
			}
		}

		// 2. 获取并校验 page_size
		pageSize := DefaultPageSize
		if s := c.Query("page_size"); s != "" {
			if val, err := strconv.Atoi(s); err == nil && val > 0 && val <= MaxPageSize {
				pageSize = val
			}
		}

		// 3. 计算 offset
		offset := (page - 1) * pageSize

		// 4. 存入上下文
		c.Set("pagination", &Pagination{
			Page:     page,
			PageSize: pageSize,
			Offset:   offset,
		})

		// 5. 设置响应头(便于调试)
		c.Header("X-Page", strconv.Itoa(page))
		c.Header("X-Page-Size", strconv.Itoa(pageSize))

		c.Next()
	}
}

// GetPagination 从上下文获取分页信息
func GetPagination(c *gin.Context) *Pagination {
	if v, exists := c.Get("pagination"); exists {
		if p, ok := v.(*Pagination); ok {
			return p
		}
	}
	return &Pagination{
		Page:     DefaultPage,
		PageSize: DefaultPageSize,
	}
}

2. 统一响应 (response/response.go)

package response

import (
	"net/http"

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

// Response 统一响应结构
type Response struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data,omitempty"`
}

// Success 成功响应
func Success(c *gin.Context, data interface{}) {
	c.JSON(http.StatusOK, Response{
		Code:    0,
		Message: "success",
		Data:    data,
	})
}

// PageResponse 分页数据
type PageResponse struct {
	Page     int         `json:"page"`
	PageSize int         `json:"page_size"`
	Total    int64       `json:"total"`
	Items    interface{} `json:"items"`
}

// Page 分页成功响应
func Page(c *gin.Context, page, pageSize int, total int64, items interface{}) {
	Success(c, PageResponse{
		Page:     page,
		PageSize: pageSize,
		Total:    total,
		Items:    items,
	})
}

// Error 错误响应
func Error(c *gin.Context, code int, message string) {
	c.JSON(code, Response{
		Code:    code,
		Message: message,
	})
}

3. 用户 Handler (handler/user.go)

package handler

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"yourapp/middleware"
	"yourapp/response"
	"yourapp/service"
)

// UserHandler 用户处理器
type UserHandler struct {
	userService *service.UserService
}

func NewUserHandler() *UserHandler {
	return &UserHandler{
		userService: service.NewUserService(),
	}
}

// GetUserList 用户列表接口(代码干净多了!)
func (h *UserHandler) GetUserList(c *gin.Context) {
	// 1. 从中间件获取分页
	p := middleware.GetPagination(c)

	// 2. 调用服务层
	users, total, err := h.userService.List(p.Offset, p.PageSize)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	// 3. 统一响应
	response.Page(c, p.Page, p.PageSize, total, users)
}

4. 服务层 (service/user.go)

package service

import (
	"yourapp/model"
	"yourapp/repository"
)

// UserService 用户服务
type UserService struct {
	repo *repository.UserRepository
}

func NewUserService() *UserService {
	return &UserService{
		repo: repository.NewUserRepository(),
	}
}

// List 获取用户列表
func (s *UserService) List(offset, limit int) ([]model.User, int64, error) {
	// 查询数据
	users, err := s.repo.List(offset, limit)
	if err != nil {
		return nil, 0, err
	}

	// 查询总数
	total, err := s.repo.Count()
	if err != nil {
		return nil, 0, err
	}

	return users, total, nil
}

5. 路由注册 (main.go)

package main

import (
	"github.com/gin-gonic/gin"
	"yourapp/handler"
	"yourapp/middleware"
)

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

	// 应用分页中间件(仅对需要分页的接口)
	api := r.Group("/api", middleware.PaginationMiddleware())
	{
		userHandler := handler.NewUserHandler()
		api.GET("/users", userHandler.GetUserList)
		api.GET("/orders", handler.GetOrderList)  // 复用!
		api.GET("/products", handler.GetProductList)  // 复用!
	}

	r.Run(":8080")
}

小红的内心独白

"这次重构花了 2 天,但值了! 中间件一写,所有接口都能用。 统一响应后,前端同事说对接舒服多了。 还写了单元测试,心里踏实。 这才是工程师该有的样子!"

高级方案的改进

改进点初级方案高级方案提升
代码复用❌ 每个接口复制✅ 中间件统一处理📈 90%
参数校验❌ 无校验✅ 边界检查🛡️ 安全
错误处理❌ 静默忽略✅ 显式返回📊 可追踪
响应格式❌ 不统一✅ 全局统一🤝 前端友好
分层架构❌ 耦合✅ Handler-Service-Repo🏗️ 清晰

但问题还没解决完

┌─────────────────────────────────────────────────────────┐
│  👴 架构师的质疑                                         │
│  ─────────────────────────────────────────────────────  │
│  ✅ 代码质量提升了                                       │
│  ⚠️  但 context 的 valueinterface{},类型不安全       │
│  ⚠️  响应 Data 是 interface{},泛型时代还这样?          │
│  ⚠️  如果加排序、过滤,中间件要改吗?                    │
│  ⚠️  测试还是得启动 Gin 引擎,不够纯粹                   │
│  ─────────────────────────────────────────────────────  │
│  结论:还有优化空间                                      │
└─────────────────────────────────────────────────────────┘

👴 第三阶段:资深架构师的实现

人物介绍

老张,10 年 + 经验,前大厂架构师
特点:追求极致,考虑长远
口头禅:"设计决定上限"

架构师的思考

┌─────────────────────────────────────────────────────────┐
│  老张的架构思考                                          │
│  ─────────────────────────────────────────────────────  │
│                                                          │
│  问题 1: Gin 的 c.Set/Getinterface{},类型不安全      │
│  → 解决:用 context.WithValue + 类型安全的 key           │
│                                                          │
│  问题 2: 响应 Data 是 interface{},泛型白用了            │
│  → 解决:Go 1.18+ 泛型,类型安全的响应                   │
│                                                          │
│  问题 3: 分页参数固定,扩展性差                          │
│  → 解决:Query 对象,支持排序、过滤等扩展                │
│                                                          │
│  问题 4: 测试依赖 Gin 引擎                               │
│  → 解决:业务逻辑与 HTTP 解耦,纯函数测试                │
│                                                          │
│  问题 5: 中间件链不好管理                                │
│  → 解决:中间件组合,可配置                              │
└─────────────────────────────────────────────────────────┘

代码实现

1. 查询参数 (query/query.go)

package query

import (
	"errors"
	"net/url"
	"strconv"
	"strings"
)

// 常量
const (
	DefaultPage     = 1
	DefaultPageSize = 20
	MaxPageSize     = 100
)

// 错误
var (
	ErrInvalidPage     = errors.New("invalid page parameter")
	ErrInvalidPageSize = errors.New("invalid page_size parameter")
	ErrInvalidSort     = errors.New("invalid sort field")
)

// Query 通用查询参数(支持扩展)
type Query struct {
	Page     int      `json:"page"`
	PageSize int      `json:"page_size"`
	Offset   int      `json:"-"`
	Sort     string   `json:"sort,omitempty"`
	Order    string   `json:"order,omitempty"`
	Filters  []Filter `json:"filters,omitempty"`
}

// Filter 过滤条件
type Filter struct {
	Field string `json:"field"`
	Op    string `json:"op"`  // eq, gt, lt, like
	Value string `json:"value"`
}

// ParseQuery 解析 URL 参数
func ParseQuery(values url.Values) (*Query, error) {
	q := &Query{
		Page:     DefaultPage,
		PageSize: DefaultPageSize,
		Sort:     "id",
		Order:    "asc",
	}

	// 解析 page
	if p := values.Get("page"); p != "" {
		page, err := strconv.Atoi(p)
		if err != nil || page < 1 {
			return nil, ErrInvalidPage
		}
		q.Page = page
	}

	// 解析 page_size
	if s := values.Get("page_size"); s != "" {
		size, err := strconv.Atoi(s)
		if err != nil || size < 1 || size > MaxPageSize {
			return nil, ErrInvalidPageSize
		}
		q.PageSize = size
	}

	// 解析排序
	if sort := values.Get("sort"); sort != "" {
		if !isValidSortField(sort) {
			return nil, ErrInvalidSort
		}
		q.Sort = sort
	}

	// 解析排序方向
	if order := values.Get("order"); order != "" {
		order = strings.ToLower(order)
		if order != "asc" && order != "desc" {
			order = "asc"
		}
		q.Order = order
	}

	// 计算 offset
	q.Offset = (q.Page - 1) * q.PageSize

	return q, nil
}

// 合法的排序字段(防止 SQL 注入)
var allowedSortFields = map[string]bool{
	"id":         true,
	"name":       true,
	"created_at": true,
	"updated_at": true,
}

func isValidSortField(field string) bool {
	return allowedSortFields[field]
}

// ToSQL 转换为 SQL 条件
func (q *Query) ToSQL() (limit, offset int, orderBy string) {
	return q.PageSize, q.Offset, q.Sort + " " + q.Order
}

2. 类型安全的上下文 (middleware/pagination.go)

package middleware

import (
	"context"
	"net/http"

	"github.com/gin-gonic/gin"
	"yourapp/query"
)

// contextKey 类型安全的上下文键
type contextKey struct {
	name string
}

var queryKey = &contextKey{"query"}

// PaginationMiddleware 分页中间件
func PaginationMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 1. 解析查询参数
		q, err := query.ParseQuery(c.Request.URL.Query())
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
			c.Abort()
			return
		}

		// 2. 存入上下文(类型安全!)
		ctx := context.WithValue(c.Request.Context(), queryKey, q)
		c.Request = c.Request.WithContext(ctx)

		// 3. 设置响应头
		c.Header("X-Page", strconv.Itoa(q.Page))
		c.Header("X-Page-Size", strconv.Itoa(q.PageSize))

		c.Next()
	}
}

// GetQuery 从上下文获取查询参数(类型安全!)
func GetQuery(c *gin.Context) *query.Query {
	if q, ok := c.Request.Context().Value(queryKey).(*query.Query); ok {
		return q
	}
	// 返回默认值(防御性编程)
	return &query.Query{
		Page:     query.DefaultPage,
		PageSize: query.DefaultPageSize,
	}
}

3. 泛型统一响应 (response/response.go)

package response

import (
	"net/http"

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

// Response 泛型统一响应
type Response[T any] struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    T      `json:"data,omitempty"`
}

// PageResponse 泛型分页响应
type PageResponse[T any] struct {
	Page     int   `json:"page"`
	PageSize int   `json:"page_size"`
	Total    int64 `json:"total"`
	Items    []T   `json:"items"`
}

// Success 泛型成功响应
func Success[T any](c *gin.Context, data T) {
	c.JSON(http.StatusOK, Response[T]{
		Code:    0,
		Message: "success",
		Data:    data,
	})
}

// Page 泛型分页响应
func Page[T any](c *gin.Context, page, pageSize int, total int64, items []T) {
	c.JSON(http.StatusOK, Response[PageResponse[T]]{
		Code:    0,
		Message: "success",
		Data: PageResponse[T]{
			Page:     page,
			PageSize: pageSize,
			Total:    total,
			Items:    items,
		},
	})
}

// Error 错误响应
func Error(c *gin.Context, code int, message string) {
	c.JSON(code, Response[any]{
		Code:    code,
		Message: message,
	})
}

4. 用户 Handler (handler/user.go)

package handler

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"yourapp/middleware"
	"yourapp/model"
	"yourapp/response"
	"yourapp/service"
)

// UserHandler 用户处理器
type UserHandler struct {
	userService UserService
}

// UserService 接口抽象(便于测试!)
type UserService interface {
	List(q *query.Query) ([]model.User, int64, error)
}

func NewUserHandler(service UserService) *UserHandler {
	return &UserHandler{userService: service}
}

// GetUserList 用户列表接口(极致干净!)
func (h *UserHandler) GetUserList(c *gin.Context) {
	// 1. 从上下文获取查询(无 HTTP 细节!)
	q := middleware.GetQuery(c)

	// 2. 调用服务层
	users, total, err := h.userService.List(q)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	// 3. 泛型响应(类型安全!)
	response.Page(c, q.Page, q.PageSize, total, users)
}

5. 服务层 (service/user.go)

package service

import (
	"yourapp/model"
	"yourapp/query"
	"yourapp/repository"
)

// UserService 用户服务
type UserService struct {
	repo repository.UserRepository
}

func NewUserService(repo repository.UserRepository) *UserService {
	return &UserService{repo: repo}
}

// List 获取用户列表(支持排序、过滤!)
func (s *UserService) List(q *query.Query) ([]model.User, int64, error) {
	// 查询数据(支持排序)
	users, err := s.repo.List(q.Offset, q.PageSize, q.Sort, q.Order)
	if err != nil {
		return nil, 0, err
	}

	// 查询总数
	total, err := s.repo.Count(q.Filters)
	if err != nil {
		return nil, 0, err
	}

	return users, total, nil
}

6. 单元测试 (handler/user_test.go)

package handler

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"yourapp/model"
	"yourapp/query"
)

// MockUserService 模拟服务
type MockUserService struct {
	mock.Mock
}

func (m *MockUserService) List(q *query.Query) ([]model.User, int64, error) {
	args := m.Called(q)
	return args.Get(0).([]model.User), args.Get(1).(int64), args.Error(2)
}

func TestGetUserList_Success(t *testing.T) {
	// 1. 设置 Gin 测试模式
	gin.SetMode(gin.TestMode)

	// 2. 创建 Mock
	mockService := new(MockUserService)
	mockService.On("List", mock.Anything).Return([]model.User{
		{ID: 1, Name: "Alice"},
		{ID: 2, Name: "Bob"},
	}, int64(100), nil)

	// 3. 创建 Handler
	handler := NewUserHandler(mockService)

	// 4. 创建请求
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("GET", "/api/users?page=1&page_size=10", nil)

	// 5. 调用 Handler
	handler.GetUserList(c)

	// 6. 断言
	assert.Equal(t, http.StatusOK, w.Code)
	assert.Contains(t, w.Body.String(), "Alice")
	mockService.AssertExpectations(t)
}

func TestGetUserList_ServiceError(t *testing.T) {
	gin.SetMode(gin.TestMode)

	mockService := new(MockUserService)
	mockService.On("List", mock.Anything).Return([]model.User{}, int64(0), assert.AnError)

	handler := NewUserHandler(mockService)

	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("GET", "/api/users", nil)

	handler.GetUserList(c)

	assert.Equal(t, http.StatusInternalServerError, w.Code)
}

7. 路由注册 (main.go)

package main

import (
	"log"

	"github.com/gin-gonic/gin"
	"yourapp/handler"
	"yourapp/middleware"
	"yourapp/repository"
	"yourapp/service"
)

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

	// 依赖注入
	userRepo := repository.NewUserRepository()
	userService := service.NewUserService(userRepo)
	userHandler := handler.NewUserHandler(userService)

	// 中间件链
	api := r.Group("/api")
	{
		// 需要分页的接口
		paged := api.Group("", middleware.PaginationMiddleware())
		{
			paged.GET("/users", userHandler.GetUserList)
			paged.GET("/orders", handler.GetOrderList)
			paged.GET("/products", handler.GetProductList)
		}

		// 不需要分页的接口
		api.GET("/users/:id", userHandler.GetUserByID)
		api.POST("/users", userHandler.CreateUser)
	}

	log.Println("Server running on :8080")
	r.Run(":8080")
}

老张的内心独白

"这套架构,可以支撑公司 3-5 年的发展。 类型安全,泛型响应,接口抽象,单元测试。 新人来了也能快速上手,因为约定清晰。 架构不是炫技,是让团队走得更快更稳。 这才是工程师的终极形态。"


📊 三阶段对比总结

代码质量对比

维度初级方案高级方案资深方案
代码行数~50 行~200 行~350 行
文件数1 个5 个8 个
类型安全⚠️ interface{}✅ 泛型
错误处理❌ 忽略✅ 显式✅ 显式 + 类型
代码复用❌ 无✅ 中间件✅ 中间件 + 接口
测试覆盖❌ 无⚠️ 集成测试✅ 单元测试
扩展性❌ 困难⚠️ 需修改✅ 无需修改
可维护性⭐⭐⭐⭐⭐⭐⭐⭐

架构演进图

┌─────────────────────────────────────────────────────────┐
│                    架构演进路线图                        │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  初级阶段              高级阶段              资深阶段    │
│  ┌─────────┐          ┌─────────┐          ┌───────── │
│  │ Handler │          │ Handler │          │ Handler │ │
│  │  +      │    →     │  +      │    →     │  +      │ │
│  │  Logic  │          │ Service │          │ Service │ │
│  └─────────          │  +      │          │  +      │ │
│                       │ Repo    │          │ Repo    │ │
│                       └─────────┘          │  +      │ │
│                                            │ Query   │ │
│                                            │  +      │ │
│                                            │ Generic │ │
│                                            └─────────┘ │
│                                                          │
│  耦合                 分层                  解耦 + 泛型   │
└─────────────────────────────────────────────────────────┘

能力成长对照

能力维度初级工程师高级工程师资深架构师
代码质量能跑就行注重规范追求极致
抽象能力就事论事提取复用设计模式
错误处理忽略捕获返回类型安全
测试意识集成测试单元测试
扩展思维当前需求近期扩展长期演进
团队协作独立开发代码评审架构设计

🎯 核心设计原则总结

┌─────────────────────────────────────────────────────────┐
│              资深架构师的 6 大设计原则                    │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  1️⃣  关注点分离    → HTTP 层与业务层彻底解耦            │
│                                                          │
│  2️⃣  类型安全      → 泛型 + 类型安全的 context key       │
│                                                          │
│  3️⃣  失败快速      → 参数校验在边界,错误不进入业务层    │
│                                                          │
│  4️⃣  接口抽象      → 依赖接口而非实现,便于测试和替换    │
│                                                          │
│  5️⃣  统一约定      → 响应格式、参数命名、错误码全局统一  │
│                                                          │
│  6️⃣  面向扩展      → Query 对象支持排序、过滤等未来需求  │
│                                                          │
└─────────────────────────────────────────────────────────┘

💡 给不同阶段工程师的建议

给初级工程师

┌─────────────────────────────────────────────────────────┐
│  📌 你的成长路径                                         │
│  ─────────────────────────────────────────────────────  │
│  1. 先让代码跑起来(功能正确)                           │
│  2. 学习错误处理(不要忽略 error)                       │
│  3. 学习代码复用(提取公共逻辑)                         │
│  4. 学习写测试(保证质量)                               │
│  5. 学习架构设计(长远考虑)                             │
│  ─────────────────────────────────────────────────────  │
│  💬 记住:每个资深工程师都曾是初级工程师                  │
└─────────────────────────────────────────────────────────┘

给高级工程师

┌─────────────────────────────────────────────────────────┐
│  📌 你的突破方向                                         │
│  ─────────────────────────────────────────────────────  │
│  1. 深入学习 Go 泛型(类型安全)                         │
│  2. 掌握设计模式(接口抽象)                             │
│  3. 关注代码可测试性(依赖注入)                         │
│  4. 学习架构思维(系统视角)                             │
│  5. 培养技术影响力(带团队)                             │
│  ─────────────────────────────────────────────────────  │
│  💬 记住:代码质量决定你的职业上限                        │
└─────────────────────────────────────────────────────────┘

给资深工程师

┌─────────────────────────────────────────────────────────┐
│  📌 你的责任                                             │
│  ─────────────────────────────────────────────────────  │
│  1. 设计可演进的架构(3-5 年视角)                        │
│  2. 建立团队规范(代码、测试、评审)                     │
│  3. 培养新人(传承经验)                                 │
│  4. 技术选型权衡(没有银弹)                             │
│  5. 平衡完美与交付( pragmatism)                        │
│  ─────────────────────────────────────────────────────  │
│  💬 记住:架构师的價值是让团队走得更快更稳                │
└─────────────────────────────────────────────────────────┘