Go中创建QueryContext是否存在非法内存访问?求排查建议
问题分析与解决建议
关于跨函数传递rows的怀疑
跨函数传递*sql.Rows本身是完全合理的,Go标准库database/sql的设计允许这种用法,这不是引发内存错误的原因。
错误原因排查
从报错栈看,问题出在gosnowflake驱动的snowflakeRows.Close方法中,出现了空指针引用(无效内存地址)。结合代码和报错信息,可能的原因包括:
- 并发访问
rows对象:*sql.Rows并非线程安全,如果多个goroutine同时调用它的Next/Scan/Close等方法,会导致底层数据结构损坏,进而引发内存错误。 - 驱动版本bug:你使用的
gosnowflake v1.6.23版本较旧,该版本的rows.Close方法可能存在空指针处理不当的bug。 - 未正确处理
rows.Next的错误:当前代码中仅在最后检查rows.Err(),但rows.Next返回false可能是因为遍历过程中出现错误,而非单纯没有数据,这种情况下未及时处理错误可能导致后续操作异常。
解决建议
- 禁止并发操作
rows:确保rows对象在整个生命周期内仅由一个goroutine操作,避免多goroutine同时调用其方法。 - 升级
gosnowflake驱动版本:更新到最新稳定版,该问题大概率已被官方修复。 - 优化
getResultString的错误处理:在rows.Next返回false后,先检查遍历过程中是否出现错误,再判断是否无数据,修改后的代码如下:
func getResultString(rows *sql.Rows) (*string, error) { defer rows.Close() var result string if rows.Next() { if err := rows.Scan(&result); err != nil { return nil, fmt.Errorf("scan err: %w", err) } return &result, nil } // 先检查遍历是否出错 if err := rows.Err(); err != nil { return nil, fmt.Errorf("query err: %w", err) } // 确实无数据的情况 return nil, fmt.Errorf("no rows found") }
- 排查重复关闭
rows的可能:确认代码中没有其他路径重复调用rows.Close(虽然当前代码中不存在,但需排除其他分支的操作)。
内容的提问来源于stack exchange,提问作者sclee1
相关产品推荐
相关产品推荐

