关于标准库database/sql

database/sql是golang的标准库之一,它提供了一系列接口方法,用于访问关系数据库。它并不会提供数据库特有的方法,那些特有的方法交给数据库驱动去实现。

database/sql库提供了一些type。这些类型对掌握它的用法非常重要。

DB

数据库对象。 sql.DB类型代表了数据库。和其他语言不一样,它并是数据库连接。golang中的连接来自内部实现的连接池,连接的建立是惰性的,当你需要连接的时候,连接池会自动帮你创建。通常你不需要操作连接池。一切都有go来帮你完成。

Results

结果集。数据库查询的时候,都会有结果集。sql.Rows类型表示查询返回多行数据的结果集。sql.Row则表示单行查询结果的结果集。当然,对于插入更新和删除,返回的结果集类型为sql.Result。

Statements

语句。sql.Stmt类型表示sql查询语句,例如DDL,DML等类似的sql语句。可以把当成prepare语句构造查询,也可以直接使用sql.DB的函数对其操作。

而通常工作中我们可能更多的是用https://github.com/jmoiron/sqlx包来操作数据库

sqlx是基于标准库database/sql的扩展,并且我们可以通过sqlx操作各种类型的数据如

和其他语言不通的是,查询数据库的时候需要创建一个连接,对于go而言则是需要创建一个数据库对象,连接将会在查询需要的时候,由连接池创建并维护,使用sql.Open函数创建数据库对象,第一个参数是数据库驱动名,第二个参数是一个连接字符串

关于数据库的增删查改

增加数据

关于增加数据几个小知识点:

关于插入数据的时候占位符是通过问号:?

插入数据的后可以通过LastInsertId可以获取插入数据的id

通过RowsAffected可以获取受影响的行数

执行sql语句是通过exec

一个简单的使用例子:

package main

import ("github.com/jmoiron/sqlx"_"github.com/go-sql-driver/mysql"

"fmt")

func main() {

Db,err:=sqlx.Open("mysql","root:123456@tcp(192.168.14.7:3306)/godb")if err !=nil{

fmt.Println("connect to mysql failed,",err)

return

}

defer Db.Close()

fmt.Println("connect to mysql success")//执行sql语句,切记这里的占位符是?

result,err := Db.Exec("INSERT INTO user_info(username,sex,email)VALUES (?,?,?)","user01","男","8989@qq.com")if err !=nil{

fmt.Println("insert failed,",err)

}//通过LastInsertId可以获取插入数据的id

userId,err:=result.LastInsertId()//通过RowsAffected可以获取受影响的行数

rowCount,err:=result.RowsAffected()

fmt.Println("user_id:",userId)

fmt.Println("rowCount:",rowCount)

}

通过Exec方法插入数据,返回的结果是一个sql.Result类型

查询数据

下面是一个查询的例子代码:

//执行查询操作

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()

使用了Query方法执行select查询语句,返回的是一个sql.Rows类型的结果集

迭代后者的Next方法,然后使用Scan方法给变量s赋值,以便取出结果。最后再把结果集关闭(释放连接)。

同样的我们还可以通过Exec方式执行查询语句

但是因为Exec返回的是一个sql.Result类型,从官网这里:

https://golang.google.cn/pkg/database/sql/#typeResult

我们可以直接这个接口里只有两个方法:LastInsertId(),RowsAffected()

我们还可以通过Db.Get()方法获取查询的数据,将查询的数据保存到一个结构体中

//Get执行查询操作

type user_info struct {

Username string `db:"username"`

Email string `db:"email"`

}

var userInfo user_info

err= Db.Get(&userInfo,"SELECT username,email FROM user_info WHERE user_id=5")if err !=nil{

fmt.Println(err)

return

}

fmt.Println(userInfo)

这样获取的一个数据,如果我们需要获取多行数据信息还可以通过Db.Select方法获取数据,代码例子为:

var userList []*user_info

err= Db.Select(&userList,"SELECT username,email FROM user_info WHERE user_id>5")if err !=nil{

fmt.Println(err)

return

}

fmt.Println(userList)

for _,v:=range userList{

fmt.Println(v)

}

通过Db.Select方法将查询的多行数据保存在一个切片中,然后就可以通过循环的方式获取每行数据

更新数据

下面是一个更新的例子,这里是通过Exec的方式执行的

//更新数据

results,err := Db.Exec("UPDATE user_info SET username=? where user_id=?","golang",5)if err !=nil{

fmt.Println("update data fail,err:",err)

return

}

fmt.Println(results.RowsAffected())

删除数据

下面是一个删除的例子,同样是通过Exec的方式执行的

//删除数据

results,err := Db.Exec("DELETE from user_info where user_id=?",5)if err !=nil{

fmt.Println("delete data fail,err:",err)

return

}

fmt.Println(results.RowsAffected())

通过上面的简单例子,对golang操作mysql的增删查改,有了一个基本的了解,下面整理一下重点内容

sql.DB

当我们调用sqlx.Open()可以获取一个sql.DB对象,sql.DB是数据库的抽象,切记它不是数据库连接,sqlx.Open()只是验证数据库参数,并没不创建数据库连接。sql.DB提供了和数据库交互的函数,同时也管理维护一个数据库连接池,并且对于多gegoroutines也是安全的

sql.DB表示是数据库抽象,因此你有几个数据库就需要为每一个数据库创建一个sql.DB对象。因为它维护了一个连接池,因此不需要频繁的创建和销毁。

连接池

只用sql.Open函数创建连接池,可是此时只是初始化了连接池,并没有创建任何连接。连接创建都是惰性的,只有当真正使用到连接的时候,连接池才会创建连接。连接池很重要,它直接影响着你的程序行为。

连接池的工作原来却相当简单。当你的函数(例如Exec,Query)调用需要访问底层数据库的时候,函数首先会向连接池请求一个连接。如果连接池有空闲的连接,则返回给函数。否则连接池将会创建一个新的连接给函数。一旦连接给了函数,连接则归属于函数。函数执行完毕后,要不把连接所属权归还给连接池,要么传递给下一个需要连接的(Rows)对象,最后使用完连接的对象也会把连接释放回到连接池。

请求连接的函数有几个,执行完毕处理连接的方式也不同:

db.Ping() 调用完毕后会马上把连接返回给连接池。

db.Exec() 调用完毕后会马上把连接返回给连接池,但是它返回的Result对象还保留这连接的引用,当后面的代码需要处理结果集的时候连接将会被重用。

db.Query() 调用完毕后会将连接传递给sql.Rows类型,当然后者迭代完毕或者显示的调用.Clonse()方法后,连接将会被释放回到连接池。

db.QueryRow()调用完毕后会将连接传递给sql.Row类型,当.Scan()方法调用之后把连接释放回到连接池。

db.Begin() 调用完毕后将连接传递给sql.Tx类型对象,当.Commit()或.Rollback()方法调用后释放连接。

每个连接都是惰性的,如何验证sql.Open调用之后,sql.DB对象可用,通过db.Ping()初始化

代码例子:

package main

import ("github.com/jmoiron/sqlx"_"github.com/go-sql-driver/mysql"

"fmt")

func main() {

Db, err := sqlx.Open("mysql", "root:123456@tcp(192.168.50.166:3306)/godb")if err !=nil {

fmt.Println("connect to mysql failed,", err)

return

}

defer Db.Close()

fmt.Println("connect to mysql success")

err=Db.Ping()if err !=nil{

fmt.Println(err)

return

}

fmt.Println("ping success")

}

需要知道:当调用了ping之后,连接池一定会初始化一个数据连接

连接失败

database/sql 其实帮我们做了很多事情,我们不用见擦汗连接失败的情况,当我们进行数据库操作的时候,如果连接失败,database/sql 会帮我们处理,它会自动连接2次,这个如果查看源码中我们可以看到如下的代码:

// ExecContext executes a querywithout returning any rows.// The args are for any placeholder parameters in the query.

func (db*DB) ExecContext(ctx context.Context, querystring, args ...interface{}) (Result, error) {

var res Result

var err error

for i := 0; i < maxBadConnRetries; i++{

res, err= db.exec(ctx, query, args, cachedOrNewConn)if err !=driver.ErrBadConn {

break

}

}if err ==driver.ErrBadConn {

return db.exec(ctx,query, args, alwaysNewConn)

}

return res, err

}

上述代码中变量maxBadConnRetries小时如果连接失败尝试的次数,默认是2

关于连接池配置

db.SetMaxIdleConns(n int) 设置连接池中的保持连接的最大连接数。默认也是0,表示连接池不会保持释放会连接池中的连接的连接状态:即当连接释放回到连接池的时候,连接将会被关闭。这会导致连接再连接池中频繁的关闭和创建。

db.SetMaxOpenConns(n int) 设置打开数据库的最大连接数。包含正在使用的连接和连接池的连接。如果你的函数调用需要申请一个连接,并且连接池已经没有了连接或者连接数达到了最大连接数。此时的函数调用将会被block,直到有可用的连接才会返回。设置这个值可以避免并发太高导致连接mysql出现too many connections的错误。该函数的默认设置是0,表示无限制。

db.SetConnMaxLifetime(d time.Duration) 设置连接可以被使用的最长有效时间,如果过期,连接将被拒绝

go 返回mysql数组_Go基础之--操作Mysql(一)相关推荐

  1. go mysql rows.next_Go基础之--操作Mysql(二)

    在上一篇文章中主要整理了Golang连接mysql以及一些基本的操作,并进行了大概介绍,这篇文章对增删查改进行详细的整理 读取数据 在上一篇文章中整理查询数据的时候,使用了Query的方法查询,其实d ...

  2. PHP访问mysql的常用函数,PHP操作MySQL数据库常用函数

    PHP操作MySQL数据库常用函数 php操作mysql数据库,俗称天龙八步: 第一步:连接数据库 第二步:判断连接错误 第三步:选择数据库 第四步:设置字符集 第五步:准备SQL语句 第六步:执行并 ...

  3. .NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper

    .NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper 參考演示样例代码,例如以下所看到的: /// <summary>/// MySql 数 ...

  4. go 语言 mysql_Go语言基础之操作MySQL

    MySQL是常用的关系型数据库,本文介绍了Go语言如何操作MySQL数据库. Go操作MySQL 连接 Go语言中的database/sql包提供了保证SQL或类SQL数据库的泛用接口,并不提供具体的 ...

  5. go mysql教学_Go语言之对Mysql简单操作

    操作mysql用到的库是sqlx 需要先安装sqlx和mysql,sqlx是在mysql驱动之上封装的包 go get "github.com/go-sql-driver/mysql&quo ...

  6. 【PHP+MySQL学习笔记】php操作MySQL数据库中语句

    我们常常用conn.php文件来建立与数据库的链接,然后在所需的文件中利用include 进行调用.这样有效防止对数据库属性的改动 而引起其他有关文件对数据调用的错误. 现在来看一个conn.php文 ...

  7. sqlalchemy mysql教程_python使用SQLAlchemy操作MySQL

    SQLAlchemy是Python编程语言下的一款开源软件,提供了SQL工具包及对象关系映射(ORM)工具,使用MIT许可证发行.SQLAlchemy首次发行于2006年2月,并迅速地在Python社 ...

  8. c语言mysql自动重连接_c++操作mysql数据库

    就拿查询MySQL获取结果集并在页面上显示数据为例来分析. HTTP请求由C级别的程序比如Apache/Nginx处理(Java的HTTP服务用的是Java开发的Tomcat等), PHP则调用内置在 ...

  9. mysql mysqli 设置,mysqli函数操作mysql实例

    php利用mysqli操作mysql数据库的类,实现增删改查 说明: 全类利用了mysqli函数库操作,需要提供SQL实现数据库的增删改查. 前几天在csdn上总结了mysqli的函数库,但只不过是对 ...

最新文章

  1. 活动|跟着微软一起,拥抱开源吧!
  2. 高性能mysql主存架构
  3. java整形怎么转字符串型_java整型与字符串互转
  4. @RequestParam与@PathVariable的区别
  5. linux下执行shell脚本文件,Linux下使用shell脚本自动执行脚本文件
  6. Title:eNSP 映射到外网
  7. [中国剩余定理]【学习笔记】
  8. Python助力中学数学教学:绘图验证反比例函数与矩形交点的关系
  9. 郁金香VC外挂教程(全) 翻录版 免Key(精品教程)
  10. IDEA初使用:解决搜狗输入法不跟随BUG
  11. Python排序算法---冒泡排序
  12. Python爬取王者荣耀手游中的游戏英雄角色
  13. Atititi 版本管理 rc final rtm ga release 软件的生命周期中一般分4个版本
  14. eclipse及tomcat设置编码
  15. 一篇文章让小白了解什么是软件测试
  16. 智能混音插件 – iZotope Neutron Advanced 3.11 win-mac
  17. 编程比赛三大赛制介绍(ACM赛制、OI赛制、IOI赛制)
  18. 简单代码变出超个性化的QQ昵称
  19. Preempt_RT Linux技术文档(一)技术基础(中英文对照)
  20. 在Edge(Chrome内核)中设置使用Google搜索并设置点击搜索结果默认打开新的标签页

热门文章

  1. 数学知识在游戏中的运用
  2. bigpipe merge对F5做批量配置
  3. 这批.Net程序员水平不行啊!居然ASP.NET Core Middleware都不会用
  4. 晕了!这个配置值从哪来的?
  5. 【litrpa专题】首个rpa程序,使用litrpa采集百度地图地铁数据
  6. ML.NET Cookbook:(5)如何查看中间过程数据?
  7. 通过 .NET NativeAOT 实现用户体验升级
  8. IdentityServer4系列 | 简化模式
  9. 使用 C# sdk 连接 高可用的 rabbitmq 镜像集群
  10. 快速了解 ASP.NET Core Blazor