go database/sql: document that Rows.Close must be called

sr4lhrrt  于 7个月前  发布在  Go
关注(0)|答案(4)|浏览(70)

如果不调用 Rows.Close,会导致资源泄漏。尽管使用示例调用了 defer rows.Close(),但对于 QueryContext 的调用者来说,可能不容易意识到 Rows 结果是可关闭的,并忘记调用它。
Rows 的文档以及任何返回 Rows 的函数都应该声明调用者有责任调用 Close。
此外,示例表明,对于只读查询,可以忽略 Close 的错误,但不应忽略更新操作中的错误。在这方面,数据库类似于可读或可写的文件;这一点也值得明确指出。
另请参阅 #33938

gcmastyq

gcmastyq1#

https://golang.org/cl/333989提到了这个问题:database/sql: document that *Rows must be closed after Query

kuarbcqp

kuarbcqp2#

在使用rows.Next时,我们需要显式地关闭它吗?例如,在以下代码中,如果没有更多的结果集,它会自动关闭。

https://cs.opensource.google/go/go/+/refs/tags/go1.21.1:src/database/sql/sql.go;drc=894d24d617bb72d6e1bed7b143f9f7a0ac16b844;l=3033
场景1:for循环没有返回任何错误

for rows.Next() {
  // no possibility of any abnormal exit here. 
}

场景2:由于扫描行时出现某些错误而从for循环返回

for rows.Next() {
   err := rows.Scan()

   if err != nil {
         return err
   }
}

我的理解是,
在场景1中,由于我们没有显式地关闭行,是否会导致资源泄漏?
在场景2中,由于我们没有关闭行和rows.Next(),因此会出现资源泄漏。
但是作为良好的实践,我们应该显式地关闭它。
有人能确认我的理解是否正确吗?
谢谢!

1aaf6o9v

1aaf6o9v3#

我的理解是,
在场景1中,是否会因为我们没有明确关闭行而导致资源泄漏?
在场景2中,由于我们没有关闭行且rows.Next()无法关闭行,因此会出现资源泄漏。但作为一种良好的实践,我们应该明确地关闭它。
有人能确认我的理解是否正确吗?
https://github.blog/2020-05-20-three-bugs-in-the-go-mysql-driver中搜索名为"The race"的部分,以查找一个有趣的故事,其中不调用Close导致了一个非常微妙的bug,即使在第一种循环中仍然会影响用户(据我了解)。该帖子观察到几乎没有人会正确调用Close,因此可以说驱动程序实现者应该更加谨慎;文档并不是非常明确。驱动程序后来已经更改为更加谨慎,但我认为假设场景1是安全的是不慎重的。

ulydmbyx

ulydmbyx4#

通过搜索来到这里,后来发现了这个优秀的教程:http://go-database-sql.org/index.html
上面提到的惊喜在http://go-database-sql.org/errors.html中提到。

相关问题