当我在golang中使用预准备语句时,是否总是需要推迟stmt.close()?

时间:2018-03-12 10:42:10

标签: sql database go

根据这里的帖子http://go-database-sql.org/modifying.html,没有延迟stmt.close()。但是,sql包中有一个stmt.close()API。我似乎无法找到有关在使用预准备语句时是否有必要推迟关闭stmt的信息。因此,问题 - 当我在golang中使用预准备语句时,我是否总是需要推迟stmt.close()?

1 个答案:

答案 0 :(得分:2)

使用defer不是要求,它是便利,它提供安全。重要的是,如果你创建/准备一个语句(它在内部使用一些资源并且也可能在数据库服务器本身中使用资源),那么在某个时候,将来某些时候你会调用它的Close()方法以便释放由它分配的资源。

即使您的函数突然结束(例如,您有一个早期的return语句,或者即使您的函数发生混乱),也会执行延迟函数,因此使用defer关闭资源可以确保代码安全不泄漏资源和/或记忆。

请注意,defer仅在周围函数返回时运行。可能存在以前可能或甚至适当地关闭语句,而不是等到周围函数返回的情况。一个很好的例子可能是,如果你有一个for循环进行多次迭代,你不希望每次迭代中创建的所有语句都保留资源,直到for循环完成。在这种情况下,建议在下一次迭代开始之前关闭资源。在这种情况下,您只需编写一个stmt.Close()而不是defer stmt.Close(),因为后者只有在函数返回时才会立即关闭该语句。

另请注意,将循环的主体“外包”到单独的函数中也可以在单独的函数中使用defer,其中延迟关闭将在下一次迭代开始之前发生。这个变体可能是你在循环体中使用匿名函数(函数文字),你也有机会使用defer,例如:

for _, v := range values {
    func() {
        stmt, err := db.Prepare("INSERT INTO users(name) VALUES(?)")
        if err != nil {
            // handle error
            return
        }
        defer stmt.Close()

        // Use stmt...
    }()
}