PS:本文是看到一个很好的教学网页,觉得很好,下面的内容基本都是直接翻译的。
网站链接:http://go-database-sql.org/index.html
官方的database.sql
包中提供了好用的数据库操作接口,但是这些接口需要相应的方法才能高效的利用否则可能导致问题。
sql.DB是数据库操作的关键抽象对象,提供sql查询、结果返回、事务操作、连接开闭、连接池维护等功能。
导入具体数据库驱动的方法
1 |
|
有些数据库鼓励你去直接使用包中的函数,但这是很不明智的,使用上面的方法可以引入驱动,但不直接使用,而是利用sql.DB对象进行操作,这样更符合Go的设计、使用效率更高,针对接口编程兼容性也更好。
创建DB对象
1 |
|
sql.Open()函数其实并没有真正创建数据库连接,而是推迟到进行数据库操作时才连接。所以为了验证数据库是否有效,可以用下面的语句:
1 |
|
注意,上面代码中defer db.Close()
是我们常用的方法,及时关闭数据库连接。但是在使用sql.DB对象时,应该尽量延长对象生存周期,通过参数传递、全局作用域等方式利用DB对象。如果频繁创建、关闭DB对象,会发生一系列网络、数据库问题,因为这不是正确使用DB对象的方法。DB对象本身会在后台维护一个连接池,具体细节我们就不用管了。
sql.Query()会返回rows
1 |
|
注意要在结束rows的迭代后检查rows.Err(),并且要及时调用rows.Close()释放连接给连接池,在rows使用的过程中连接是一直被占用的。
可以利用db.Prepare进行带参数的查询
1 |
|
※Prepare也可能会造成连接资源占用的问题,在实际使用中要考虑到。
在不关心SQL执行结果的情况下,最好用db.Exec()函数
1 |
|
上面对Query的使用是错误的,返回的rows会一直得不到释放,虽然最终会被垃圾回收机制释放,但是会耗费很多时间、占用了资源。
由于数据库的各种操作和连接都可能产生错误,所以应该在每一次操作都尽量查看是否存在错误,避免程序错误执行。注意进行错误码比较时不要用魔法数字,要用常量。
可置NULL的字段的处理方式:
1 |
|
在执行事务操作时,当前的连接是处于保持连接并准备执行事务状态的,所以这个过程如果执行其他不相关的sql语句,本质上是其他新的连接执行的,这点要意识到。
对返回的rows的字段数量和类型未知的情况下,可以用sql.RawBytes
1 |
|
关于连接池,可以利用一系列参数设置函数,针对自己的业务进行调参优化。
1 |
|
目前对存储过程(Stored Procedures)的调用支持的不太好,调用后无法返回正确的结果。(这个可能得直接调用驱动包中的函数)