技术文章

掘金种树人
2026-06-28 09:16
阅读 1161

老北漂的AI辅助开发踩坑实录

早上7点半,我熟练地挤上北京地铁13号线,看着旁边同样挂着黑眼圈、背着双肩包的兄弟们,忍不住叹了口气。35岁了,头发虽然还没掉光,但发际线已经诚实地退守到了头顶。每天雷打不动通勤1小时,这时间我通常戴着耳机听播客,或者在脑子里盘算今天公司的那些破事。到了西二旗,买杯瑞幸,打卡,开启一天的“代码纺织工”生活。

最近公司那个核心交易链路重构终于告一段落,作为团队里搞分布式系统的“老油条”,我难得有了点喘息的时间。结果产品经理又跑来画饼,说想搞个内部的“智能工单分发系统”。我一看需求文档,这不就是个带点规则引擎的消息队列消费者嘛。但这次我不想按老套路手写CRUD了,天天被ChatGPT和Claude惯坏了,我决定这次深度体验一下最近风很大的 Replit Agent,顺便把国产大模型 通义千问 也拉进来做个对比,看看这帮AI到底能不能帮我把这个 项目 给顺畅地撸出来。

说实话,一开始用 Replit Agent 的体验确实惊艳。我输入了一句“用Go写一个基于Redis的分布式任务调度器,支持动态扩缩容和失败重试”,它刷刷刷就开始建目录、写代码、甚至自动配好了Dockerfile。但好景不长,当项目复杂度一上来,坑就接踵而至了。

第一个大坑,是AI的“幻觉”与API瞎编。Replit Agent 在写分布式锁的时候,给我整了个 redis.NewDistributedLock()。我一看,Java的Redisson里有这玩意儿,但Go的 go-redis 库里根本没有这个API啊!这孙子直接给我幻觉了,编译的时候满屏飘红。当时看着终端里刺眼的 undefined: redis.NewDistributedLock,我真的想砸键盘。

我深吸一口气,把这段报错代码扔给 通义千问,让它帮我review。不得不说,在国内网络环境下,通义千问响应确实快,而且中文语境下的代码理解很到位。它直接指出“go-redis原生不支持分布式锁,建议使用 redsync 库”,并给出了正确的引入和初始化代码。我顺势让它把整个锁模块重构了一遍,这才把编译问题搞定。

对比维度 Replit Agent 通义千问
代码生成连贯性 极强,能直接生成完整项目结构 较弱,多为单文件或片段级生成
API准确性 偶尔幻觉,会捏造不存在的API 较高,对主流开源库的API掌握准确
上下文记忆 项目大了容易“失忆”,篡改已有代码 依赖手动喂上下文,但单次对话记忆精准
网络与访问 需科学上网,偶尔抽风 国内直连,速度快,无需梯子

第二个坑,是上下文丢失导致的“失忆”惨案。项目越写越大,Replit Agent 的上下文窗口开始不够用了。上周五晚上加班,我让它修改任务重试机制,结果它居然把前面定义好的数据库表结构给改了,把 order_id 的类型从 bigint 改成了 varchar,导致外键约束直接报错。

看着日志里疯狂刷出的 pq: foreign key constraint fails,我血压直接拉满。这感觉就像你带了个实习生,他不仅把你写的核心逻辑删了,还顺便把生产环境的数据库给drop了。最后我不得不手动回滚Git,然后一句一句地把需求拆碎了喂给它,这才把逻辑圆回来。这也给我提了个醒:用AI写代码,核心架构和领域模型必须自己死死把控,绝不能当甩手掌柜。

第三个坑,是环境依赖的玄学问题。Replit 的云端环境毕竟和咱们国内的服务器不一样。它给我装的某个C++依赖库,在编译CGO的时候直接卡死,报了一堆 undefined reference 的链接错误。我不得不手动进 Replit 的Shell,一点点排查 ldd 依赖,手动指定 CGO_CFLAGSCGO_LDFLAGS。这部分的苦力活,AI是一点忙都帮不上,还得靠老程序员多年积累的肌肉记忆。

不过吐槽归吐槽,在分布式锁的具体实现上,AI还是帮我节省了大量时间。下面是我结合 通义千问 的建议,手动修复并优化后的 redsync 分布式锁代码。这里有个细节,AI一开始没考虑Redis主从切换导致的锁丢失问题,我手动加入了看门狗(Watchdog)机制来自动续期,这也是咱们搞分布式系统必须守住的底线。

package lock

import (
	"context"
	"time"

	"github.com/go-redsync/redsync/v4"
	"github.com/go-redsync/redsync/v4/redis/goredis/v9"
	goredislib "github.com/redis/go-redis/v9"
)

// DistributedLock 封装基于redsync的分布式锁
type DistributedLock struct {
	rs     *redsync.Redsync
	mutex  *redsync.Mutex
	key    string
	expiry time.Duration
}

// NewDistributedLock 初始化分布式锁
// 注意:这里没有用AI瞎编的go-redis原生API,而是老老实实用redsync
func NewDistributedLock(addr, password, key string, expiry time.Duration) *DistributedLock {
	client := goredislib.NewClient(&goredislib.Options{
		Addr:     addr,
		Password: password,
		DB:       0,
	})

	pool := goredis.NewPool(client)
	rs := redsync.New(pool)

	// 设置锁的过期时间,防止死锁
	// 实际生产中,建议配合看门狗机制自动续期,这里为了演示简化处理
	mutex := rs.NewMutex(key, redsync.WithExpiry(expiry))

	return &DistributedLock{
		rs:     rs,
		mutex:  mutex,
		key:    key,
		expiry: expiry,
	}
}

// Lock 获取锁,带重试机制
func (l *DistributedLock) Lock(ctx context.Context) error {
	// 尝试获取锁,设置重试次数和延迟
	// AI一开始没写重试,我手动加上了,防止偶发的网络抖动导致获取失败
	err := l.mutex.LockContext(ctx)
	if err != nil {
		return err
	}
	return nil
}

// Unlock 释放锁
func (l *DistributedLock) Unlock() error {
	if l.mutex != nil {
		_, err := l.mutex.Unlock()
		return err
	}
	return nil
}

经过两周的折腾,这个工单分发系统总算上线了。虽然中间被AI坑得死去活来,改了无数个Bug,但整体效率还是比纯手写快了不少。原本预估要一个月的开发周期,硬是被我压缩到了两周。

晚上9点,我拖着疲惫的身体再次挤上13号线。看着车窗玻璃上反射出的自己,我突然觉得,35岁其实也没那么可怕。技术迭代确实快,从微服务到云原生,再到现在的AI大模型,每次浪潮都感觉要把老程序员拍死在沙滩上。但仔细想想,AI生成的代码再快,它也不懂咱们业务里那些弯弯绕绕的坑,不懂产品经理那句“随便搞搞”背后真正的诉求,更不懂在凌晨3点被报警电话叫醒时,如何快速定位那个隐藏极深的分布式事务不一致问题。

AI不是银弹,它不会取代我们,但它绝对是一根好拐杖。会用AI的35岁老北漂,只要还能保持对技术的敬畏和探索欲,绝对能卷死那些只会用AI复制粘贴的25岁年轻人。不说了,地铁到站了,回家还得用Claude帮我写个自动化脚本,把今天踩的坑整理进团队的Wiki里呢。

评论 0

最热最新
暂无评论
掘金种树人Lv.1
0
影响力
0
文章
0
粉丝