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

Go+Postgres使用QueryRow遇pq错误:unexpected Parse response 'C'

解决 pq: unexpected Parse response 'C' 错误

问题分析

你遇到的pq: unexpected Parse response 'C'错误,虽常与未关闭*sql.Rows相关,但你使用的是QueryRow返回的*sql.Row(无Close方法)。核心问题出在事务上下文里,当QueryRow返回sql.ErrNoRows时,底层PostgreSQL连接的结果集未被完全消费——同一事务复用的连接残留上一次查询的状态,导致后续查询的协议交互冲突,触发驱动解析错误。

解决方案

替换查询部分的QueryRow为Query,手动控制rows的关闭,确保每次查询的结果集被彻底清理:

type Queryable interface {
    Query(query string, args ...interface{}) (*sql.Rows, error)
    QueryRow(query string, args ...interface{}) *sql.Row
}

func GetOrCreateArticle(q Queryable, article *entity.Article) (id int64, err error) {
    const selectQuery string = "SELECT id FROM articles WHERE link = $1"
    const insertQuery string = "INSERT INTO articles (link, title) VALUES ($1, $2) RETURNING id"

    // 使用Query替代QueryRow,手动管理rows生命周期
    rows, err := q.Query(selectQuery, article.Link)
    if err != nil {
        return 0, err
    }
    defer rows.Close() // 确保无论执行结果如何,rows都会被关闭

    // 读取查询结果
    found := false
    for rows.Next() {
        if err := rows.Scan(&id); err != nil {
            return 0, err
        }
        found = true
    }
    // 检查rows遍历过程中的错误
    if err := rows.Err(); err != nil {
        return 0, err
    }

    // 未找到则执行插入
    if !found {
        err = q.QueryRow(insertQuery, article.Link, article.Title).Scan(&id)
    }

    return id, err
}

关键说明

  • Query返回的*sql.Rows必须通过defer rows.Close()手动关闭,即使无查询结果,也能确保底层连接的结果集被完全清理,避免事务内连接状态异常。
  • 遍历rows.Next()后必须检查rows.Err(),捕获遍历过程中可能出现的隐性错误。
  • 插入操作仍用QueryRow即可,因为插入仅返回单行结果,无需手动管理rows。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 08:24:53