You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang+PostgreSQL开发Telegram Bot时重复添加用户问题排查

问题分析与修复:Telegram机器人注册功能重复添加用户

问题根源

1. SQL拼接引发的类型安全问题

代码直接用fmt.Sprintf拼接SQL语句,未采用参数化查询,会导致:

  • 若Telegram用户ID(int64)超出数据库uuid字段的类型范围(比如字段是int而非bigint),插入数据会被截断,后续用完整ID查询时无法匹配到被截断的记录,进而重复插入。
  • 存在SQL注入风险,同时无法利用PostgreSQL的类型校验机制。

2. 字段类型不匹配

如果users表的uuid字段定义为int(32位),而Telegram用户ID是64位整数,插入时会自动截断高位,导致存储的ID与实际用户ID不一致,IsUserInDB自然查不到对应记录。

3. 逻辑瑕疵(非核心问题,但需优化)

handleMessages中添加用户后直接return err(此时err为nil),逻辑不够清晰;且未处理添加用户时的主键冲突(后续若将uuid设为主键则会遇到)。

修复方案

第一步:修正数据库字段类型

确保users表的uuid字段为bigint,匹配Telegram用户ID的int64类型:

ALTER TABLE users ALTER COLUMN uuid TYPE bigint;

建议将uuid设为主键,从数据库层面杜绝重复插入:

ALTER TABLE users ADD PRIMARY KEY (uuid);

第二步:替换为参数化查询(核心修复)

永远不要用字符串拼接构建SQL,改用PostgreSQL的参数占位符($n格式)保证类型安全:

修复IsUserInDB函数

func IsUserInDB(uuid int64) (bool, error) {
    var exists bool
    query := "SELECT EXISTS(SELECT 1 FROM users WHERE uuid = $1);"
    err := Db.QueryRow(query, uuid).Scan(&exists)
    return exists, err
}

修复AddUserToDB函数

func AddUserToDB(column string, row interface{}) error {
    query := fmt.Sprintf("INSERT INTO users (%s) VALUES ($1);", column)
    _, err := Db.Exec(query, row)
    return err
}

第三步:优化消息处理逻辑

添加主键冲突处理,同时补充用户提示:

func (b *Bot) handleMessages(message *tgbotapi.Message) error {
    switch message.Text {
    case "register":
        exists, err := data.IsUserInDB(message.From.ID)
        if err != nil {
            return err
        }
        if !exists {
            err := data.AddUserToDB("uuid", message.From.ID)
            if err != nil {
                // 捕获PostgreSQL主键冲突错误(错误码23505)
                if pgErr, ok := err.(*pq.Error); ok && pgErr.Code == "23505" {
                    msg := tgbotapi.NewMessage(message.Chat.ID, "你已经注册过了!")
                    _, sendErr := b.bot.Send(msg)
                    return sendErr
                }
                return err
            }
            // 注册成功提示
            msg := tgbotapi.NewMessage(message.Chat.ID, "注册成功!")
            _, sendErr := b.bot.Send(msg)
            return sendErr
        }
        // 已注册提示
        msg := tgbotapi.NewMessage(message.Chat.ID, "你已经注册过了!")
        _, err = b.bot.Send(msg)
        return err
    default:
        msg := tgbotapi.NewMessage(message.Chat.ID, "未知指令...")
        _, err := b.bot.Send(msg)
        return err
    }
}

注:需导入github.com/lib/pq包以捕获PostgreSQL错误码。

验证修复

  1. 执行数据库字段修改语句。
  2. 替换代码后重新编译运行。
  3. 重复发送register指令,机器人将正确识别已注册用户,不再重复添加记录。

内容的提问来源于stack exchange,提问作者Alexander Turok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:36:06