5.1 go-sql-driver/mysql

Go使用SQL与类SQL数据库的惯例是通过标准库database/sql。这是一个对关系型数据库的通用抽象,它提供了标准的、轻量的、面向行的接口。Go本身不提供具体数据库驱动,只提供驱动接口和管理,要使用数据库,除了database/sql包本身,还需要引入想使用的特定数据库驱动。

现推荐一个我在项目中用到的驱动:

https://github.com/go-sql-driver/mysql

特征

  • 轻巧快速
  • Native Go实现。没有C-bindings,只是纯粹的Go
  • 通过TCP / IPv4,TCP / IPv6,Unix域套接字或自定义协议进行连接
  • 自动处理断开的连接
  • 自动连接池(通过database / sql包)
  • 支持大于16MB的查询
  • 全力sql.RawBytes支持。
  • LONG DATA准备好的报表中的智能处理
  • LOAD DATA LOCAL INFILE通过文件白名单和io.Reader支持提供安全支持
  • 可选的time.Time解析
  • 可选的占位符插值

要求

  • 去1.8或更高。我们的目标是支持Go的3个最新版本。
  • MySQL(4.1 +),MariaDB,Percona Server,Google CloudSQL或Sphinx(2.2.3+)

安装

使用shell中的go工具将包简单地安装到$ GOPATH

  1. $ go get -u github.com/go-sql-driver/mysql

确保Git已安装在您的计算机和系统中PATH

用法

使用sql.Open方法会创建一个数据库连接池db。这个db不是数据库连接,它是一个连接池,只有当真正数据库通信的时候才创建连接。例如这里的db.Ping的操作。db.SetMaxIdleConns(20)db.SetMaxOpenConns(20)分别设置数据库的空闲连接和最大打开连接,即向Mysql服务端发出的所有连接的最大数目。

注意:sql.DB对象是为了长连接而设计的,不要频繁Open()Close()数据库。而应该为每个待访问的数据库创建一个sql.DB示例,并在用完前一直保留它。需要时可将其作为参数传递,或注册为全局对象。

如果没有按照database/sql设计的意图,不把sql.DB当成长期对象来用而频繁开关启停,就可能遭遇各式各样的错误:无法复用和共享连接,耗尽网络资源,由于TCP连接保持在TIME_WAIT状态而间断性的失败等

示例:

  1. package main
  2. import (
  3. "database/sql"
  4. _ "github.com/go-sql-driver/mysql"
  5. "log"
  6. )
  7. func main() {
  8. db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=true")
  9. defer db.Close()
  10. if err != nil {
  11. log.Fatalln(err)
  12. }
  13. //用于设置闲置的连接数。如果 <= 0, 则没有空闲连接会被保留
  14. db.SetMaxIdleConns(0)
  15. //用于设置最大打开的连接数,默认值为0表示不限制。
  16. db.SetMaxOpenConns(30)
  17. if err := db.Ping(); err != nil {
  18. log.Fatalln(err)
  19. }
  20. }

测试表

  1. CREATE TABLE `user` (
  2. `id` int(10) NOT NULL COMMENT '主键',
  3. `name` varchar(100) NOT NULL DEFAULT '' COMMENT '名字',
  4. `ctime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间'
  5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

示例:

  1. package main
  2. import (
  3. "database/sql"
  4. "fmt"
  5. _ "github.com/go-sql-driver/mysql"
  6. "log"
  7. "time"
  8. )
  9. var db *sql.DB
  10. func main() {
  11. var err error
  12. db, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=true&&loc=Local")
  13. //parseTime是查询结果是否自动解析为时间。
  14. //loc是MySQL的时区设置。
  15. defer db.Close()
  16. if err != nil {
  17. log.Fatalln(err)
  18. }
  19. //用于设置闲置的连接数。如果 <= 0, 则没有空闲连接会被保留
  20. db.SetMaxIdleConns(0)
  21. //用于设置最大打开的连接数,默认值为0表示不限制。
  22. db.SetMaxOpenConns(30)
  23. if err := db.Ping(); err != nil {
  24. log.Fatalln(err)
  25. }
  26. //插入
  27. insert()
  28. //更新
  29. update()
  30. //查询
  31. query()
  32. //删除
  33. delete()
  34. }
  35. func insert() {
  36. tx, err := db.Begin()
  37. if err != nil {
  38. return
  39. }
  40. ctime := time.Now().Unix()
  41. defer tx.Rollback()
  42. stmt, err := tx.Prepare("INSERT INTO user (name,ctime) VALUES (?,?)")
  43. if err != nil {
  44. return
  45. }
  46. rs, err := stmt.Exec("李四", ctime)
  47. if err != nil {
  48. return
  49. }
  50. err = tx.Commit()
  51. if err != nil {
  52. return
  53. }
  54. id, err := rs.LastInsertId()
  55. fmt.Println(id)
  56. defer stmt.Close() //runs here!
  57. return
  58. }
  59. func update() {
  60. tx, err := db.Begin()
  61. if err != nil {
  62. return
  63. }
  64. defer tx.Rollback()
  65. stmt, err := tx.Prepare("UPDATE user SET name=? WHERE id=?")
  66. if err != nil {
  67. return
  68. }
  69. _, err = stmt.Exec("zhangsan", 1)
  70. if err != nil {
  71. return
  72. }
  73. err = tx.Commit()
  74. if err != nil {
  75. return
  76. }
  77. defer stmt.Close()
  78. return
  79. }
  80. func query() {
  81. rows, err := db.Query("SELECT id,name,ctime FROM user ")
  82. defer rows.Close()
  83. if err != nil {
  84. return
  85. }
  86. for rows.Next() {
  87. var id, ctime int64
  88. var name string
  89. rows.Scan(&id, &name, &ctime)
  90. fmt.Println(id, name, ctime)
  91. }
  92. if err = rows.Err(); err != nil {
  93. return
  94. }
  95. return
  96. }
  97. func delete() {
  98. tx, err := db.Begin()
  99. if err != nil {
  100. return
  101. }
  102. defer tx.Rollback()
  103. stmt, err := tx.Prepare("DELETE FROM user WHERE id=?")
  104. if err != nil {
  105. return
  106. }
  107. _, err = stmt.Exec(1)
  108. if err != nil {
  109. return
  110. }
  111. err = tx.Commit()
  112. if err != nil {
  113. return
  114. }
  115. defer stmt.Close()
  116. return
  117. }

links