驱动

github.com/go-sql-driver/mysql

请求一个连接的函数有好几种,执行完毕处理连接的方式稍有差别,大致如下:

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

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

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

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

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

    连接DB

    sql.Open的第一个参数是driver名称,第二个参数是driver连接数据库的信息,各个driver可能不同。DB不是连接,并且只有当需要使用时才会创建连接,如果想立即验证连接,需要用Ping()方法,如下:

    err = db.Ping()if err != nil {
       // do something here
    }

    sql.DB的设计就是用来作为长连接使用的。不要频繁Open, Close。比较好的做法是,为每个不同的datastore建一个DB对象,保持这些对象Open。如果需要短连接,那么把DB作为参数传入function,而不要在function中Open, Close。

    读取DB

    如果方法包含Query,那么这个方法是用于查询并返回rows的。其他情况应该用Exec()

    var (
       id int
       name string
    )
    rows, err := db.Query("select id, name from users where id = ?", 1)if err != nil {
       log.Fatal(err)
    }
    defer rows.Close()for rows.Next() {
       err := rows.Scan(&id, &name)
       if err != nil {
           log.Fatal(err)
       }
       log.Println(id, name)
    }
    err = rows.Err()if err != nil {
       log.Fatal(err)
    }

    上面代码的过程为:db.Query()表示向数据库发送一个query,defer rows.Close()非常重要,遍历rows使用rows.Next(), 把遍历到的数据存入变量使用rows.Scan(), 遍历完成后检查error。有几点需要注意:

    1. 检查遍历是否有error

    2. 结果集(rows)未关闭前,底层的连接处于繁忙状态。当遍历读到最后一条记录时,会发生一个内部EOF错误,自动调用rows.Close(),但是如果提前退出循环,rows不会关闭,连接不会回到连接池中,连接也不会关闭。所以手动关闭非常重要。rows.Close()可以多次调用,是无害操作。

    单行Query

    err在Scan后才产生,所以可以如下写:

    var name stringerr = db.QueryRow("select name from users where id = ?", 1).Scan(&name)if err != nil {
       log.Fatal(err)
    }
    fmt.Println(name)

    修改数据,事务

    一般用Prepare()和Exec()完成INSERTUPDATEDELETE操作。

    事务

    db.Begin()开始事务,Commit() 或 Rollback()关闭事务。Tx从连接池中取出一个连接,在关闭之前都是使用这个连接。Tx不能和DB层的BEGINCOMMIT混合使用。

    如果你需要通过多条语句修改连接状态,你必须使用Tx,例如:

    • 创建仅对单个连接可见的临时表

    • 设置变量,例如SET @var := somevalue

    • 改变连接选项,例如字符集,超时

    处理Error

    循环Rows的Error

    如果循环中发生错误会自动运行rows.Close(),用rows.Err()接收这个错误,Close方法可以多次调用。循环之后判断error是非常必要的。

    关闭Resultsets时的error

    如果你在rows遍历结束之前退出循环,必须手动关闭

关于连接池

  1. 当需要连接,且连接池中没有可用连接时,新的连接就会被创建。

  2. 默认没有连接上限,这可能会导致数据库产生错误“too many connections”

  3. db.SetMaxIdleConns(N)设置最大空闲连接数

  4. db.SetMaxOpenConns(N)设置最大打开连接数

  5. 长时间保持空闲连接可能会导致db timeout

补充:

2、数据库

2.1、type DB struct{}

DB是一个数据库句柄,代表一个具有零到多个底层连接的连接池。

它可以安全的被多个go程同时使用。

连接池的大小可以用SetMaxIdleConns方法控制。

2.2、常用方法

(1)func Open(driverName, dataSourceName string) (*DB, error)

打开数据库,返回数据库句柄,DB可以安全的被多个go程同时使用,并会维护自身的闲置连接池。

Open函数只需调用一次,很少需要关闭DB。

(2)func (db *DB) Driver() driver.Driver

返回数据库下层驱动。

(3)func (db *DB) Ping() error

检查与数据库的连接是否仍有效,如果需要会创建连接。

(4)func (db *DB) Close() error

关闭数据库,释放任何打开的资源。

一般不会关闭DB,因为DB句柄通常被多个go程共享,并长期活跃。

(5)func (db *DB) SetMaxOpenConns(n int)

设置与数据库建立连接的最大数目。

如果n大于0且小于最大闲置连接数,会将最大闲置连接数减小到匹配最大开启连接数的限制。

如果n <= 0,不会限制最大开启连接数,默认为0(无限制)。

(6)func (db *DB) SetMaxIdleConns(n int)

设置连接池中的最大闲置连接数。

如果n大于最大开启连接数,则新的最大闲置连接数会减小到匹配最大开启连接数的限制。

如果n <= 0,不会保留闲置连接。

(7)func (db *DB) Exec(query string, args ...interface{}) (Result, error)

执行一次命令(包括查询、删除、更新、插入等),不返回任何执行结果。

参数args表示query中的占位参数。

(8)func (db *DB) Query(query string, args ...interface{}) (*Rows, error)

执行一次查询,返回多行结果(即Rows),一般用于执行select命令。

(9)func (db *DB) QueryRow(query string, args ...interface{}) *Row

执行一次查询,并期望返回最多一行结果(即Row)。

总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。

(10)func (db *DB) Prepare(query string) (*Stmt, error)

创建一个准备好的状态用于之后的查询和命令。

返回值可以同时执行多个查询和命令。

(11)func (db *DB) Begin() (*Tx, error)

开始一个事务。

隔离水平由数据库驱动决定。

3、数据表

3.1、type Rows{}

Rows是查询的结果。

它的游标指向结果集的第零行,使用Next方法来遍历各行结果。

3.2、常用方法

(1)func (rs *Rows) Columns() ([]string, error)

返回列名。

如果Rows已经关闭会返回错误。

(2)func (rs *Rows) Scan(dest ...interface{}) error

Scan将当前行各列结果填充进dest指定的各个值中。

如果某个参数的类型为*[]byte,Scan会保存对应数据的拷贝,该拷贝为调用者所有,可以安全的,修改或无限期的保存。

如果参数类型为*RawBytes可以避免拷贝;参见RawBytes的文档获取其使用的约束。

如果某个参数的类型为*interface{},Scan会不做转换的拷贝底层驱动提供的值。

如果值的类型为[]byte,会进行数据的拷贝,调用者可以安全使用该值。

(3)func (rs *Rows) Next() bool

Next准备用于Scan方法的下一行结果。

如果成功会返回真,如果没有下一行或者出现错误会返回假。

每一次调用Scan方法,甚至包括第一次调用该方法,都必须在前面先调用Next方法。

(4)func (rs *Rows) Close() error

关闭Rows,阻止对其更多的列举。

如果Next方法返回假,Rows会自动关闭。

检查Err方法结果的条件。

Close方法是幂等的(多次调用无效的成功),不影响Err方法的结果。

(5)func (rs *Rows) Err() error

Err返回可能的、在迭代时出现的错误。

Err需在显式或隐式调用Close方法后调用。

4、数据行

4.1、type Row{}

QueryRow方法返回Row,代表单行查询结果。

4.2、常用方法

(1)func (r *Row) Scan(dest ...interface{}) error

Scan将该行查询结果各列分别保存进dest参数指定的值中。

如果该查询匹配多行,Scan会使用第一行结果并丢弃其余各行。

如果没有匹配查询的行,Scan会返回ErrNoRows。

5、SQL命令状态

5.1、type Stmt struct{}

Stmt是准备好的状态。

Stmt可以安全的被多个go程同时使用。

5.2、常用方法

(1)func (s *Stmt) Exec(args ...interface{}) (Result, error)

使用提供的参数执行准备好的命令状态,返回Result类型的该状态执行结果的总结。

(2)func (s *Stmt) Query(args ...interface{}) (*Rows, error)

使用提供的参数执行准备好的查询状态,返回Rows类型查询结果。

(3)func (s *Stmt) QueryRow(args ...interface{}) *Row

使用提供的参数执行准备好的查询状态。

如果在执行时遇到了错误,该错误会被延迟,直到返回值的Scan方法被调用时才释放。

返回值总是非nil的。

如果没有查询到结果,*Row类型返回值的Scan方法会返回ErrNoRows;否则,Scan方法会扫描结果第一行并丢弃其余行。

(4)func (s *Stmt) Close() error

关闭状态。

6、事务

6.1、type Tx struct{}

Tx代表一个进行中的数据库事务。

一次事务必须以对Commit或Rollback的调用结束。

调用Commit或Rollback后,所有对事务的操作都会失败并返回错误值ErrTxDone。

6.2、常用方法

(1)func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)

执行命令,但不返回结果。例如执行insert和update。

(2)func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error)

执行查询并返回零到多行结果(Rows),一般执行select命令。

(3)func (tx *Tx) QueryRow(query string, args ...interface{}) *Row

执行查询并期望返回最多一行结果(Row)。

总是返回非nil的结果,查询失败的错误会延迟到在调用该结果的Scan方法时释放。

(4)func (tx *Tx) Prepare(query string) (*Stmt, error)

准备一个专用于该事务的状态。

返回的该事务专属状态操作在Tx递交会回滚后不能再使用。

(5)func (tx *Tx) Stmt(stmt *Stmt) *Stmt

使用已存在的状态生成一个该事务特定的状态。

(6)func (tx *Tx) Commit() error

提交事务。

(7)func (tx *Tx) Rollback() error

回滚事务。

最新文章

  1. Entity Framework 教程——概述
  2. Delphi项目构成之项目文件DPR
  3. 【noiOJ】p1481
  4. scrollWidth的巧妙运用
  5. progressBar 自定义
  6. RichtextBox去除闪烁光标
  7. VC2010编写Dll文件(转)
  8. CodeForces 816B Karen and Coffee(前缀和,大量查询)
  9. CSS float 属性
  10. linux静态ip的设置
  11. python AES加密 ECB PKCS5
  12. Python 每日随笔
  13. 20165323 预备作业3 Linux安装及学习
  14. 吴裕雄 python深度学习与实践(3)
  15. springmvc处理日期格式
  16. 开源的PaaS方案:在OpenStack上部署CloudFoundry (一)简介
  17. builtroot make menuconfig流程
  18. Elasticsearch: 权威指南(官方教程)
  19. 巧用CSS属性visibility与opacity代替鼠标经过的jQuery事件
  20. [SCOI2007]修车 费用流 BZOJ 1070

热门文章

  1. 【Linux_Shell 脚本编程学习笔记三、分支与循环结构】
  2. OpenCV 霍夫线变换
  3. 吴裕雄--天生自然HTML学习笔记:HTML 列表
  4. 使用阿里大于平台发送短信验证码java代码实现
  5. excel中ppmt/pmt/ipmt的计算方式
  6. vm文件的优点
  7. Python字符串编码——Unicode
  8. Janet Wu price
  9. 【h5ai】搭建服务器目录
  10. 【视频+图文】带你快速掌握Java中含break语句的双重for循环