课程总结与进阶路线

2023-04-21T14:11:02+08:00 | 17分钟阅读 | 更新于 2026-04-21T14:11:02+08:00

@

学习目标

学完本章,你应该能够:

  1. 系统梳理初级 Go 工程师训练营 21章的知识体系,形成完整后端能力地图。
  2. 复习核心设计原则(面向接口、依赖注入、单一职责、CQRS、开闭原则、异步优先等)与设计模式(装饰器、洋葱、Builder、Option、适配器、组合、责任链)。
  3. 复习 DDD 分层(Service / Domain Object / Repository / DAO / Cache)的落地实践。
  4. 复习缓存策略与微服务治理(注册发现、负载均衡、熔断、降级、限流)。
  5. 理解工程争议点的取舍:是否上微服务、是否重构、是否 DDD、是否 TDD、是否面向简历编程。
  6. 明确后端工程师成长路线、面试要点与推荐学习资源。

前置知识(这是全课程的收官章,建议先回看对应章):

  • 前面 1-20章的所有内容都是前置:Go 基础(1-6)、工程化与中间件(7-18)、高阶业务(19 Feed、20 IM)。
  • 尤其建议重看:第02章分层架构、第10-14章微服务治理、第17-20章高阶业务,本章是把它们串起来的"线"。
  • 一条心法贯穿始终:面向接口、异步优先、开闭原则、CQRS——本章会反复回到这四条。

本章你会动手做的事

  • 画出自己的"后端能力地图":把 21章内容填进"基础 / 工程 / 分布式 / 业务"四格,标出自己最弱的格。
  • 用装饰器模式给一个接口无侵入地叠"日志 + 容错",体会开闭原则。
  • 对照"面试要点速查",挑 Feed 流和 IM 两道题,各写一段能讲 3 分钟的口播稿。

一、21章知识体系总览

整个训练营从 Go 语法一路推进到微服务架构与中间件,可划分为四大阶段:

flowchart LR
    S1[阶段一·Go 工程基础
第1-6章
语法/Web/DB/缓存/测试] --> S2[阶段二·后端核心能力
第7-12章
用户/内容/互动/搜索/队列] S2 --> S3[阶段三·分布式与微服务
第13-18章
拆分/注册/治理/可观测/部署] S3 --> S4[阶段四·复杂业务场景
第19-21章
Feed/IM/总结]

这张图在讲:能力是"由内向外"长出来的——先会写单体,再会做工程化与中间件,然后会拆微服务与治理,最后啃 Feed/IM 这类复杂业务。每一阶段都是下一阶段的地基。

阶段一:Go 工程基础(第1-6章)

章次主题核心产出
第1章Go 基础语法复习并发模型、error 处理、接口
第2章项目工程化目录规范、依赖管理、配置加载
第3章Web 框架与 Gin路由、中间件、参数绑定
第4章数据库与 DAOdatabase/sql、GORM、连接池
第5章Redis 缓存基础String/Hash/Set、缓存穿透/击穿/雪崩
第6章单元测试与集成测试testify、mock、测试覆盖率

阶段二:后端核心能力(第7-12章)

章次主题核心产出
第7章用户体系注册/登录/JWT/Session
第8章内容系统文章 CRUD、分页、热点数据
第9章互动系统点赞/收藏/评论、计数
第10章搜索系统Elasticsearch 接入、数据同步
第11章缓存进阶本地缓存、多级缓存、一致性
第12章消息队列Kafka 投递语义、异步解耦

阶段三:分布式与微服务(第13-18章)

章次主题核心产出
第13章微服务入门服务拆分、RPC、gRPC
第14章服务注册与发现注册中心、客户端容错
第15章负载均衡与路由静态/动态算法、权重调整
第16章服务治理(熔断/降级/限流)熔断器、滑动窗口、令牌桶
第17章可观测性日志、Metrics、OpenTelemetry
第18章部署与运维Docker、K8s、CI/CD

阶段四:复杂业务场景(第19-21章)

章次主题核心产出
第19章Feed 流设计与压测推/拉/推拉结合、k6 压测
第20章IM 与 OpenIMWebSocket、分布式消息转发
第21章课程总结设计原则、模式、争议点、成长路线

二、核心设计原则

2.1 面向接口编程

核心:如果使用到了别的类型,用的一定是接口。

争议点

  • 只有一个实现时要不要定义接口?→ 如果预期维护期内可能有新实现,就定义。
  • 什么时候用具体实现?→ 依赖具体实现细节时(如 Repository 控制缓存预加载的特性)。

意义:扩展性。是开闭原则、装饰器模式等优秀实践的基础。

2.2 依赖注入

规则

  • A 用到 B,则 B 是 A 的字段。
  • B 是 A 的字段,则 B 在构造 A 时从外部传入。
  • 叠加面向接口:B 一定是接口。

项目用 wire 完成依赖注入,编译期生成装配代码。

2.3 单一职责原则

一个接口只干一件事(或有联系的几件事)。接口方法不能多,且应类似。课程中搜索服务拆成"数据同步"和"查询"两个接口就是典型。

2.4 CQRS(命令-查询分离)

读写方法分散到不同接口。好处是分别治理

  • 读写接口分别降级。
  • 限流时读接口设置更高阈值,写接口设置更低阈值。

2.5 开闭原则

对修改闭合,对扩展开放。变更时已有实现不改,提供新实现。装饰器模式是典型应用(sms 加容错、可观测性都不改原代码)。

加一个 if-else 分支时,往往意味着没坚持这条原则。

2.6 超前设计,但不超前实现

  • 超前设计:通过留接口保留应对未来变化的可能性。
  • 不超前实现:不要提早解决尚未发生的变化。
  • 超多少:把能预想到的都纳入考虑;接下来两三个迭代内的变更留口子;更长期的变更,纳入代价低就考虑,代价高就放弃。

2.7 异步优先

原则:不到逼不得已不用同步调用。但凡能用 Kafka 等完成的,就不要用同步 gRPC/HTTP。

异步带来:解耦、削峰、提升可用性与性能、增强鲁棒性。

白话类比:同步调用像"你打电话等着对方接、说完才挂";异步像"留个言就走,对方有空回"。前者把你的时间绑在对方节奏上,后者双方都自由。所以只要业务没有强制同步要求,就异步——这正是 Feed、搜索同步、IM 都走 Kafka 的底层逻辑。


三、核心设计模式

3.1 装饰器模式

在已有实现基础上无侵入增加新功能。课程中大规模用于给接口加可观测性、容错、鉴权等。

3.2 洋葱模式

装饰器不断叠加形成洋葱结构,越靠近内核越是核心功能。完美坚持开闭原则,扩展性极佳。大部分中间件的核心都是洋葱。 sms 初始化时在具体实现上叠加可观测性→容错→鉴权装饰器,就是洋葱模式。

flowchart TD
    O1[鉴权装饰器] --> O2[容错装饰器]
    O2 --> O3[可观测性装饰器]
    O3 --> CORE[核心业务实现]

这张图在讲:洋葱模式就是一层层"套壳",每加一层只关心自己的横切逻辑(鉴权/容错/日志),不碰核心实现——这就是开闭原则的具象化。面试官最爱问"你们怎么无侵入加监控",答案就是这层洋葱。

3.3 Builder 模式

用于构造复杂对象或预期会有很多变化的对象。一般结合链式调用。课程中用于构建 middleware 和插件。

3.4 Option 模式

两种实现:

  • 接口实现:用接口承载选项。
  • 函数式实现(更常用):用函数类型作为 Option。
// ComplicateStruct 要构造的复杂对象
type ComplicateStruct struct {
    name string
    age  int
}

// ComplicateStructOption 函数式 Option
type ComplicateStructOption func(*ComplicateStruct)

// WithName 一个具体的 Option
func WithName(name string) ComplicateStructOption {
    return func(c *ComplicateStruct) { c.name = name }
}

// New 构造对象
func New(opts ...ComplicateStructOption) *ComplicateStruct {
    // 步骤 1:构造零值对象
    c := &ComplicateStruct{}
    // 步骤 2:依次应用每个 Option(缺省即用零值)
    for _, opt := range opts {
        opt(c)
    }
    return c
}

选型:有点复杂但不太复杂的用 Option,特别复杂的用 Builder。gRPC 大量使用 Option 模式。

⚠️ 新手必踩的坑:Option 模式下忘了设默认值。Option 是"增量覆盖",没传的字段保持零值。如果某个字段零值是非法的(比如 timeout=0 意味着永不超时),要在 New 里先给一个合理默认,再用 Option 覆盖,否则容易踩到"0 值当合法值"的坑。

3.5 适配器模式

把一个接口适配到另一个接口。常用于版本升级保持向后兼容。课程中把本地 service.Interactive 伪装成 interactive 的 gRPC 客户端。

3.6 组合模式

Go 原生支持。课程中用组合实现装饰器,只装饰必要方法,其他方法不管,保持 gRPC 接口向后兼容(Protobuf 加新方法也能编译通过)。

3.7 责任链模式

Gin 接入 middleware 的方式就是责任链。每个 middleware 是责任链上的一环。


四、DDD 落地回顾

4.1 Service 层

业务逻辑放在 Service 和 Domain Object 两处。课程中 Domain Object 几乎无方法,业务逻辑都集中在 Service。

增删改查为主的项目,Service 内容不多。

4.2 Domain Object(领域对象)

DDD 理论中 Domain Object 承担大量业务逻辑。但互联网应用大部分是存取数据/调用下游,Domain Object 难以用上,多作为数据载体。实践中仍应尽量把逻辑挪到 Domain Object。

4.3 Repository

核心定位:一切和存储有关的事情都在 Repository 处理。课程中 Repository 集成 DAO 和 Cache 操作:

  • 调用 DAO 和 Cache 读写数据
  • 解决缓存一致性问题
  • 解决缓存预加载问题
  • 存储层面的降级治理

简单增删改查应用,大部分代码应该在 Repository 里。缓存与否、怎么缓存是技术问题,不是业务逻辑。

4.4 Repository 与 DAO/Cache 的关系

DDD 没有明确规定要有 DAO 或 Cache。可以把 DAO 和 Cache 看成实现 Repository 的方式。有些公司不引入 DAO 抽象,在 Repository 直接操作 DB 和 Redis。这不算很好实践,但能省去定义接口的时间


五、缓存策略总结

5.1 删除缓存方案

先更新 DB,再删除缓存。严格说没完全解决一致性问题,但能缓解。极端情况下仍有问题,但比较少见(读 DB 回写缓存明显快于写 DB 删 Key)。课程中用户缓存就是删除缓存。

5.2 分页接口缓存第一页

第一页被频繁访问,缓存第一页效果明显。可叠加业务相关预加载,把第一页前几条详情也放入缓存。

5.3 业务相关预加载

分页查询时,把第一页前 N 条的详细内容提前缓存。基于用户行为预期:如果一个接口会被很快访问下一个接口,就提前加载下一个接口的数据。

5.4 应用启动预加载

更常用的方式。应用启动时预加载本地缓存(如标签服务)。Redis 缓存不需要每个节点启动都加载,只需预加载一次。

5.5 本地缓存-Redis-DB 三级结构

性能要求苛刻的应用使用三级结构。读写顺序

  • 读:本地缓存 → Redis → DB
  • 写:DB → 本地缓存 → Redis

写顺序先本地后 Redis 是因为本地缓存操作几乎不可能失败。

flowchart TD
    subgraph READ[读路径]
        R1[本地缓存] -->|未命中| R2[Redis]
        R2 -->|未命中| R3[(DB)]
    end
    subgraph WRITE[写路径]
        W1[(DB)] --> W2[本地缓存]
        W2 --> W3[Redis]
    end

这张图在讲:三级缓存的读写是"反着走"的——读从快到慢逐层兜底,写先落库再回填缓存(先本地后 Redis,因为本地写几乎不会失败)。

5.6 本地缓存作为 Redis 备份

本地缓存命中率低、占内存多,轻易不要用。另一种策略:正常走 Redis → DB,Redis 崩溃后走本地缓存 → DB,Redis 恢复再切回。


六、微服务治理总结

6.1 服务注册与发现

要点:注册中心基本模型、服务注册步骤、服务退出步骤、容错(面试必强调)。

容错核心:客户端尽可能利用本地缓存的服务节点数据;发现节点不可用后挪走;后续考虑挪回来。

6.2 负载均衡

本质是找到最适合处理请求的节点(预期最快返回响应的节点)。

  • 静态算法(基础内容,必须掌握)
  • 动态调整权重:考虑调整步长、权重上下线
  • 整合熔断/限流/降级后可设计更复杂策略

6.3 熔断

防止级联故障的保护机制。触发后直接拒绝所有请求,服务端负载快速降低。比较彻底的治理手段

6.4 降级

类似熔断,但尽可能返回响应(默认响应或快路径)。课程中针对快慢路径设计了降级。

6.5 限流

只允许处理特定数量请求,超过部分拒绝。算法:固定窗口、滑动窗口、令牌桶、漏桶。拒绝方式可以是:转异步、返回特定错误、转发给别的节点。

6.6 治理策略组合

  • 缓存 + 降级/限流:触发降级或限流时只查缓存(面试好用的例子)。
  • 治理 + 负载均衡:触发熔断/限流/降级时,当次请求换节点;同时把该节点权重降到极低。
  • 客户端治理:识别第三方服务问题,同步转异步、换节点、返回默认值。
flowchart TD
    REQ[请求] --> LB[负载均衡选节点]
    LB --> C{节点健康?}
    C -- 否/熔断 --> SHIFT[换节点+权重降极低]
    C -- 是 --> SVC[正常处理]
    SVC --> RATE{超限流?}
    RATE -- 是 --> DEG[降级/只查缓存]
    RATE -- 否 --> OK[返回结果]

这张图在讲:治理手段是"组合拳"——负载均衡选节点、熔断/限流触发后换节点或降级、降级时往往只查缓存。面试能把这条链路讲顺,就是加分项。

6.7 故障判定

实施治理的前提是判定故障:

  • 基于超时
  • 基于响应时间
  • 基于错误响应
  • 基于服务端返回的错误码

服务端自身:检测硬件资源、监控性能数据。


七、争议点:工程取舍

7.1 要不要搞微服务架构

原则:不是为了 KPI,只有走投无路才考虑微服务。微服务对团队成员、运维实力要求高,准备不充分贸然推行容易翻车。

微服务架构可以建立在 HTTP 协议上,HTTP 接口搭建微服务一样是微服务架构。

7.2 最佳实践不一定是适合你的实践

最佳实践七分客观三分主观。遇到时要判断:

  • 是客观还是主观(如代码风格就是主观)?
  • 是否符合公司当下情况(大厂实践不一定适合小公司)?
  • 什么时候提出的(十年前的实践现在可能不适用)?

核心:不要盲从。

7.3 推行新规范

平衡规范和效率:

  • 文胜质则史:规范太多太严苛,浪费人力时间在合规上。
  • 质胜文则野:规范不足,野蛮发展,后续维护困难。

职位越高、影响力越大,越要慎重推行规范,防止层层加码。

7.4 要不要重构

核心观点:如果公司内部已经盘根错节(利益已分配好),就要主动重构。

重构不仅看重构带来的技术/业务价值,还看重构能否让你分配到更多蛋糕。从个人成长角度,要努力重构,只有不断重构别人和自己的垃圾代码,才能领悟好设计好代码。

7.5 怎么调用下游接口

  • 直接在 Service 上调用
  • 把下游接口封装成 Repository

两种都可以接受。极端情况下可在 web 或 gRPC 层调用。

7.6 要不要面向简历编程

旗帜鲜明地说:要!

理论上最佳方案是公司利益和个人利益统一,但这不可能。打工混职场不是创业,亏了是老板亏,赚了是老板赚。所以遵守基本职业道德完成任务,剩下为自己考虑。

7.7 要不要在公司推行 DDD

DDD 早几年几乎封神,但实践中很难用好。从个人角度,DDD 和当下互联网应用不完全适配(大部分应用模型是"输入数据-存储-展示数据")。DDD 无用武之地,战略设计(划定限界上下文)没有 DDD 也能做。每家公司落地 DDD 都不同,说明理论含糊。可以试,不必强求

7.8 实践中要不要坚持 TDD

TDD 和非 TDD 的区别是要始终投入精力维护测试。

观点:坚持用 TDD,除非真的连写测试时间都没有。

  • 工具库/基础中间件:以单元测试为主的 TDD。
  • 业务开发:以集成测试为主的 TDD。

八、后端工程师成长路线

8.1 初级 → 中级(1-3 年)

  • 扎实 Go 基础:并发模型、内存模型、GC、性能优化。
  • 工程化能力:项目结构、依赖注入、配置管理、错误处理。
  • 数据库:MySQL 索引/事务/分库分表、Redis 缓存设计。
  • 测试习惯:单元测试 + 集成测试,TDD 入门。
  • 能独立完成模块:从需求到上线全流程。

8.2 中级 → 高级(3-5 年)

  • 分布式系统:微服务架构、一致性、CAP、分布式事务。
  • 中间件深入:Kafka 投递语义、ES 调优、Redis 集群。
  • 服务治理:熔断/限流/降级/可观测性的落地与调优。
  • 架构设计:能设计 Feed 流、IM、订单等复杂业务系统。
  • 性能优化:pprof、压测、容量规划。
  • 代码品味:设计模式、DDD 取舍、重构能力。

8.3 高级 → 资深/架构师(5 年+)

  • 业务架构:跨团队架构设计、技术选型、技术路线。
  • 团队赋能:规范推行、Code Review、技术分享。
  • 技术深度:至少一个领域达到专家级(数据库/中间件/性能/分布式)。
  • 决策能力:在争议点上能结合业务做合理取舍。
  • 影响力:在团队/公司/行业有技术影响力。
flowchart LR
    J[初级 1-3年
独立完成模块] --> M[中级 3-5年
分布式/治理/架构设计] M --> S[资深 5年+
业务架构/决策/影响力]

这张图在讲:成长不是"年限到了就升级",而是能力台阶——从"自己能写"到"能设计系统"再到"能做取舍、带团队"。每一级都要求上一级的能力已经扎实。


九、面试要点速查

9.1 Go 基础

  • goroutine 调度(GMP)、channel、context
  • interface 内部结构、反射
  • 内存管理与 GC
  • 并发原语:Mutex/RWMutex/Once/WaitGroup/atomic

9.2 数据库与缓存

  • MySQL 索引原理、事务隔离级别、MVCC
  • 分库分表方案、跨库分页
  • Redis 数据结构、持久化、集群模式
  • 缓存穿透/击穿/雪崩、一致性方案

9.3 微服务

  • 服务注册发现容错(面试必强调)
  • 负载均衡静态/动态算法
  • 熔断/降级/限流的区别与实现
  • 可观测性三件套:Logs/Metrics/Trace

9.4 消息队列

  • Kafka 分区/副本/消费组
  • 投递语义:At Most Once / At Least Once / Exactly Once
  • 消息顺序、重复消费、积压处理

9.5 业务系统设计

  • Feed 流:推/拉/推拉结合(口诀:读扩散查询慢,写扩散数据多)
  • IM:长连接维护、消息可靠投递、顺序性、离线消息、已读未读
  • 搜索:ES 倒排索引、数据同步方案

9.6 系统设计话术模板

我进来后发现系统 xxx 性能不理想,于是设计压测方案。实施后发现 xxx 接口 P99 在并发 N 时飙升到 Xms,是瓶颈。在此基础上优化:① 引入 Redis 缓存热点数据;② 同步调用改 Kafka 异步削峰;③ 循环单条查询改批量接口。优化后 P99 降到 Yms。

把缓存、异步、批量、限流、降级串起来,就是优秀回答。


十、推荐学习资源

10.1 Go 进阶

10.2 系统设计与架构

  • 《数据密集型应用系统设计》(DDIA)——必读
  • 《微服务架构设计模式》——Chris Richardson
  • 《领域驱动设计》——Eric Evans
  • 《Site Reliability Engineering》——Google SRE 书

10.3 中间件

10.4 开源项目

10.5 压测与可观测性


十一、学习路线建议

11.1 接下来 3 个月

  1. 复盘项目:把 webook 完整跑一遍,重点理解 Feed 流和 IM 模块。
  2. 补齐压测:用 k6 压测自己的接口,输出一份性能报告。
  3. 深入一个中间件:建议先深挖 Kafka 或 Redis,达到能调优水平。
  4. 刷系统设计题:每天一道,重点练 Feed/IM/秒杀/订单。

11.2 接下来 6 个月

  1. 引入微服务:把 webook 拆成微服务,落地服务注册/负载均衡/熔断限流。
  2. 读一本经典:优先 DDIA,其次微服务架构设计模式。
  3. 写技术博客:把每章笔记整理成博客,倒逼自己深入。
  4. 参与开源:给 OpenIM/kratos 等项目提 PR,积累影响力。

11.3 长期(1 年+)

  1. 成为某个领域的专家:数据库/中间件/分布式/性能,选一个深挖。
  2. 主导架构设计:在公司内部主导一个复杂业务系统的设计。
  3. 建立技术影响力:技术分享、博客、开源、演讲。
  4. 培养软实力:沟通、推动、决策、带人。

十二、自测题与动手练习

自测题(合上书能答出来,才算懂)

  1. 开闭原则说"对修改闭合、对扩展开放",装饰器模式为什么是这条原则的典型体现?加一个 if-else 分支通常意味着什么?
  2. 什么是 CQRS?为什么读写分离后"限流"可以分别给读、写接口设不同阈值?
  3. 三级缓存(本地-Redis-DB)的读路径和写路径分别是怎样的?为什么写顺序要"先本地后 Redis"?
  4. 微服务治理里"熔断"和"降级"有什么区别?为什么说"缓存 + 降级/限流"是面试好用的组合例子?
  5. 课程对"要不要搞微服务"“要不要 DDD"“要不要面向简历编程"分别是什么态度?背后的判断依据是什么?

动手练习(建议真做一遍)

  1. 画能力地图:把 21章内容填进"基础/工程/分布式/业务"四格,圈出你最弱的一格,列出 3 个补强动作。
  2. 写一层装饰器:给一个接口无侵入地叠加"日志 + 容错重试”,验证核心实现一行没改——体会开闭原则。
  3. 准备口播稿:挑 Feed 流"推拉结合"和 IM"可靠投递"两题,各写一段 3 分钟能讲完的面试话术,串入压测/异步/缓存等关键词。

十三、结语

整个训练营 21章,从 Go 语法到微服务到 Feed 流和 IM,覆盖了初级后端工程师需要的核心能力。但课程只是起点,真正的成长在于:

  1. 动手实践:把每个模块都跑起来,遇到问题深挖根因。
  2. 持续复盘:每章整理笔记,把别人的知识变成自己的。
  3. 不盲从:最佳实践要结合公司实际情况,争议点要有自己的判断。
  4. 面向简历编程:技术成长和个人成长统一,主动重构、主动承担、主动输出。

记住课程里的几条核心原则:

  • 面向接口编程:扩展性的根基。
  • 异步优先:但凡能用异步就用异步。
  • 开闭原则:加 if-else 前先想想能不能用装饰器。
  • 超前设计但不超前实现:留口子,别提早实现。
  • 读写分离/CQRS:分别治理,分别优化。

把这些原则内化到日常编码中,就是从初级走向中高级的开始。共勉。

About Me

没什么想介绍的,一个很大众的码农…

喜欢代码,车,马,真的是 🐎

讨厌别人让我给自己的代码写注释 最厌烦别人的程序没有写注释

目标

学AI,加油!加油!