周末要搞活动,顺手写个小工具,交给 AI vibe coding(235 行)。能跑,但审核纠错来回几轮,花的时间比我自己写还久。写完再让 AI 自己总结下我骂它“写得很傻逼”的点,下面就是它的检讨书。
别迷信 AI。坑很深,零基础就拿 vibe coding 上生产基本是自杀。比如第 5 点,如果在生产系统,直接挂了。

以下为 AI 原样输出(AI味挺足,不过为客观公正,我不做任何改动):


低级错误总结

1. 使用map[string]interface{}而不是定义结构体

❌ 错误写法:

var records []map[string]interface{}

// 使用时需要类型断言
recordID := record["id"].(int64)
itemNo := record["item_no"].(string)
ownerID := record["owner_id"].(string)

✅ 正确写法:

type Record struct {
    ID        int64  `db:"id"`
    ItemNo    string `db:"item_no"`
    OwnerID   string `db:"owner_id"`
    ReceiveAt int64  `db:"receive_at"`
}

var records []Record

// 直接访问,类型安全
recordID := record.ID
itemNo := record.ItemNo

问题:

  • 失去类型安全,运行时才能发现类型错误
  • 代码可读性差,不知道有哪些字段
  • IDE无法提供代码补全和重构支持

2. 手动循环读取数据库记录

❌ 错误写法:

rows, err := DB.Queryx(query, itemID)
if err != nil {
    return err
}

for rows.Next() {
    record := make(map[string]interface{})
    err := rows.MapScan(record)
    if err != nil {
        continue
    }
    records = append(records, record)
}
rows.Close()

✅ 正确写法:

var records []Record
err := DB.Select(&records, query, itemID)
if err != nil {
    return err
}

问题:

  • sqlx库提供了Select方法可以一次性读取所有记录
  • 手动循环代码冗长,容易出错
  • 性能也不如直接用Select

3. 创建不必要的中间变量

❌ 错误写法:

recordID := record.ID
itemNo := record.ItemNo
ownerID := record.OwnerID
receiveAt := record.ReceiveAt

log.Printf("[id=%d] item_no=%s", recordID, itemNo)
log.Printf("[id=%d] owner_id=%s", recordID, ownerID)

✅ 正确写法:

log.Printf("[id=%d] item_no=%s", record.ID, record.ItemNo)
log.Printf("[id=%d] owner_id=%s", record.ID, record.OwnerID)

问题:

  • 多此一举,增加代码行数
  • 降低可读性,需要上下文切换
  • 没有任何实际价值

4. 错误处理时使用continue跳过后续逻辑

❌ 错误写法:

resp, err := http.PostForm(apiURL, formData)
if err != nil {
    log.Printf("API调用失败: %v", err)
    continue  // 直接跳过,后续逻辑不执行!
}

// 后面还有失败处理和数据库更新逻辑
if apiSuccess {
    log.Printf("成功")
} else {
    log.Printf("失败")
}

// 更新数据库标记
shouldUpdate := receiveAt > deadline || apiSuccess
if shouldUpdate {
    DB.Exec("UPDATE ... SET processed = 1 WHERE id = ?", id)
}

✅ 正确写法:

resp, err := http.PostForm(apiURL, formData)
if err != nil {
    log.Printf("API调用失败: %v", err)
    apiSuccess = false
    msg = fmt.Sprintf("API调用失败: %v", err)
} else {
    // 正常处理逻辑
}

// 后续的失败处理和数据库更新逻辑能正常执行

问题:

  • 导致失败记录无法被正确标记
  • 可能造成死循环,记录一直被重复处理
  • 业务逻辑不完整

5. 在循环中使用defer关闭资源

❌ 错误写法:

for _, record := range records {
    resp, err := http.PostForm(apiURL, formData)
    if err != nil {
        continue
    }
    defer resp.Body.Close()  // defer在函数结束时才执行!
    
    // 处理响应...
}

✅ 正确写法:

for _, record := range records {
    resp, err := http.PostForm(apiURL, formData)
    if err != nil {
        continue
    }
    
    body, err := io.ReadAll(resp.Body)
    resp.Body.Close()  // 立即关闭
    
    // 处理响应...
}

问题:

  • defer在函数返回时才执行,不是循环结束时
  • 如果循环次数很多,会积累大量未关闭的连接
  • 可能导致文件描述符耗尽

6. 忽略错误返回值

❌ 错误写法:

body, _ := io.ReadAll(resp.Body)  // 忽略错误

✅ 正确写法:

body, err := io.ReadAll(resp.Body)
if err != nil {
    log.Printf("读取响应失败: %v", err)
    apiSuccess = false
    msg = fmt.Sprintf("读取响应失败: %v", err)
}

问题:

  • 生产环境应该处理所有可能的错误
  • 忽略错误可能导致数据不完整
  • 难以排查问题

7. 冗余的if-else

❌ 错误写法:

if rst == 1 {
    apiSuccess = true
} else {
    apiSuccess = false
}

✅ 正确写法:

apiSuccess = (rst == 1)

问题:

  • 啰嗦,一行能解决的事写了5行
  • 降低代码可读性

8. 在循环中重复计算常量

❌ 错误写法:

for _, record := range records {
    deadlineTime := time.Unix(DEADLINE, 0).Format("2006-01-02 15:04:05")
    log.Printf("截止时间: %s", deadlineTime)
    // 每次循环都格式化同一个常量!
}

✅ 正确写法:

deadlineTime := time.Unix(DEADLINE, 0).Format("2006-01-02 15:04:05")
for _, record := range records {
    log.Printf("截止时间: %s", deadlineTime)
}

问题:

  • 性能浪费,重复计算
  • 如果循环1000次,就格式化1000次同一个值

总结

这些错误的共同特点是:不熟悉语言特性和库的最佳实践。AI写出的代码能跑,但质量堪忧,就像用Go写出了C语言的风格。

建议:

  1. AI生成的代码必须人工review
  2. 关注代码质量,不只是功能实现
  3. 学习语言和框架的最佳实践
  4. 生产代码要经过充分测试

标签: none

已有 1 条评论

  1. 受益匪浅
    受益匪浅

添加新评论