FWDD.NET · 技术文档站

范文多多

聚焦后端工程实践:语言教程、功能实现、面试题与运维脚本。每篇都从真实踩坑场景出发,给出可直接复用的代码与取舍依据。

用 CTE 递归查询实现树形评论的分页展开

树形评论的分页是论坛和社区类产品里最容易被低估的一块。表面需求是"一页显示 20 条评论",实际难点在于:评论是嵌套的,一条根评论下面可能挂着十几层回复,你既不能让某一层的子回复被分页切口拦腰截断,也不能因为要算好层级导致每次翻页都全表扫描。很多项目最后退化成一次性把整棵树的评论全部查出来丢给前端拼,帖子一火,接口就是几百毫秒起步,内存里堆着上万行 JSON

用 IntersectionObserver 实现图片懒加载与占位占高

列表页一次性渲染 200 张商品图,首屏要下载十几 MB 的图片,用户滑动时白屏、闪烁、滚动位置乱跳,这是最典型的图片加载问题。把 loading="lazy" 加在 <img> 上只能解决「什么时候下载」,解决不了「下载之前这块地方占多高」。图片没有尺寸,浏览器在图片解码前把它当 0 高度处理,图片到达后页面被撑开,原本已经滚到第 80 条的用

用 ZSET 实现延迟任务队列:到期扫描与原子取出

订单超时关单、优惠券到期提醒、15 分钟未支付自动取消、消息重投退避——这类「到点才执行」的需求,用定时任务扫数据库是最容易想到的方案,但只要表一大、并发一高,就会出现扫全表慢、多个实例重复执行、任务取到一半进程挂掉导致丢失等问题。Redis 的 ZSET(sorted set)天生适合做这件事:score 存到期时间戳,member 存任务内容,按 sco

用 sync.Cond 实现一个有界阻塞队列

Go 标准库提供了 channel 来做协程间通信,但 channel 不支持「队列长度到达上限后单独统计丢弃次数」这类自定义策略;而在需要精细控制唤醒时机、需要复用同一把锁保护其他状态、或者需要实现「批量入队 / 批量出队」语义时,sync.Cond 是更合适的基础原语。本文从零实现一个泛型有界阻塞队列 BoundedQueue[T],包含 Put(满时阻