在上一篇文章中主要整理了Golang连接mysql以及一些基本的操作,并进行了大概介绍,这篇文章对增删查改进行详细的整理
读取数据
在上一篇文章中整理查询数据的时候,使用了Query的方法查询,其实database/sql还提供了QueryRow方法查询数据,就像之前说的database/sql连接创建都是惰性的,所以当我们通过Query查询数据的时候主要分为三个步骤:
从连接池中请求一个连接
执行查询的sql语句
将数据库连接的所属权传递给Result结果集
Query返回的结果集是sql.Rows类型。它有一个Next方法,可以迭代数据库的游标,进而获取每一行的数据,使用方法如下:
//执行查询操作
rows,err := Db.Query("SELECT email FROM user_info WHERE user_id>=5")if err !=nil{
fmt.Println("select db failed,err:",err)
return
}// 这里获取的rows是从数据库查的满足user_id>=5的所有行的email信息,rows.Next(),用于循环获取所有
for rows.Next(){
var s string
err= rows.Scan(&s)if err !=nil{
fmt.Println(err)
return
}
fmt.Println(s)
}
rows.Close()
其实当我们通过for循环迭代数据库的时候,当迭代到最后一样数据的时候,会出发一个io.EOF的信号,引发一个错误,同时go会自动调用rows.Close方法释放连接,然后返回false,此时循环将会结束退出。
通常你会正常迭代完数据然后退出循环。可是如果并没有正常的循环而因其他错误导致退出了循环。此时rows.Next处理结果集的过程并没有完成,归属于rows的连接不会被释放回到连接池。因此十分有必要正确的处理rows.Close事件。如果没有关闭rows连接,将导致大量的连接并且不会被其他函数重用,就像溢出了一样。最终将导致数据库无法使用。
所以为了避免这种情况的发生,最好的办法就是显示的调用rows.Close方法,确保连接释放,又或者使用defer指令在函数退出的时候释放连接,即使连接已经释放了,rows.Close仍然可以调用多次,是无害的。
rows.Next循环迭代的时候,因为触发了io.EOF而退出循环。为了检查是否是迭代正常退出还是异常退出,需要检查rows.Err。例如上面的代码应该改成:
//Query执行查询操作
rows,err := Db.Query("SELECT email FROM user_info WHERE user_id>=5")if err !=nil{
fmt.Println("select db failed,err:",err)
return
}// 这里获取的rows是从数据库查的满足user_id>=5的所有行的email信息,rows.Next(),用于循环获取所