diff --git a/5.1.md b/5.1.md index 24c84b24..3e9b5afc 100644 --- a/5.1.md +++ b/5.1.md @@ -42,10 +42,13 @@ Driver是一个数据库驱动的接口,他定义了一个method: Open(name } 返回的Conn只能用来进行一次goroutine的操作,也就是说不能把这个Conn应用于Go的多个goroutine里面。如下代码会出现错误 + + ... + go goroutineA (Conn) //执行查询操作 + go goroutineB (Conn) //执行插入操作 + ... - go dosomething(Conn) - -上面这样的代码会引发数据查询数据混乱,导致不知道是那个goroutine做的事情。会把goroutine A里面执行的查询返回给goroutine B执行的插入结果。 +上面这样的代码可能会导致不知道某个操作究竟是由哪个goroutine发起的,从而数据混乱,比如可能会把goroutine A里面执行的查询操作的结果返回给goroutine B从而使B错误的把此结果当成自己执行的插入结果。 第三方驱动都会定义这个函数,它会解析name参数来获取相关数据库的连接信息,解析完成后,它将使用此信息来初始化一个Conn并返回它。 @@ -60,9 +63,9 @@ Conn是一个数据库连接的接口定义,他定义了一系列方法,这 Prepare函数返回与当前连接相关的准备好Sql语句的状态,可以进行查询、删除等操作。 -Close函数关闭使得当前的连接失效,以及和当前连接相关的状态、处理。因为database/sql里面实现了建议的conn pool,所以你不要再自己去实现缓存conn之类的,这样容易引起问题。 +Close函数关闭当前的连接,以及执行释放连接拥有的资源等清理工作。因为database/sql里面实现了建议的conn pool,所以你不要再自己去实现缓存conn之类的,这样容易引起问题。 -Begin函数返回一个事务处理Tx,可以进行事物操作,回滚、递交等操作。 +Begin函数返回一个代表事务处理的Tx,通过它你可以进行查询,更新等操作,或者对事务进行回滚、递交。 ##drive.Stmt Stmt是一种准备好的状态,和Conn相关联,而且是只能应用于一个goroutine中,不能应用在多个goroutine中。 @@ -74,7 +77,7 @@ Stmt是一种准备好的状态,和Conn相关联,而且是只能应用于一 Query(args []Value) (Rows, error) } -Close函数关闭当前的链接状态,但是如果当前正在执行query,query还是有效返回raws数据。 +Close函数关闭当前的链接状态,但是如果当前正在执行query,query还是有效返回rows数据。 NumInput函数返回当前预留参数的个数,当返回>=0时数据库驱动就会智能检查调用者的参数。当数据库驱动包不知道预留参数的时候,返回-1。 @@ -94,7 +97,7 @@ Query函数执行Prepare准备好的sql,传入需要的参数执行select操 这两个函数一个用来递交一个事务,一个用来回滚事务。 ##drive.Execer -这个接口是Conn可选的可实现可不实现的接口 +这是一个Conn可选择实现的接口 type Execer interface { Exec(query string, args []Value) (Result, error) @@ -110,8 +113,9 @@ Query函数执行Prepare准备好的sql,传入需要的参数执行select操 RowsAffected() (int64, error) } -LastInsertId函数返回插入数据库之后返回自动增长字段的ID,Insert之后返回的数据 -RowsAffected函数返回通过query影响的数据库条数。 +LastInsertId函数返回由数据库执行插入操作得到的自动增长ID号。 + +RowsAffected函数返回query操作影响的数据条目数。 ##drive.Rows Rows是执行查询返回的结果集接口定义 @@ -129,7 +133,7 @@ Columns函数返回查询数据库表的字段信息,这个返回的slice和 Close函数用来关闭Rows迭代器。 -Next函数用来返回下一条数据,把数据赋值给dest。dest里面的元素必须是drive.Value的值除了string,所有的string必须转换成[]byte.如果最后没数据了,Next函数最后返回io.EOF。 +Next函数用来返回下一条数据,把数据赋值给dest。dest里面的元素必须是drive.Value的值除了string,返回的数据里面所有的string都必须要转换成[]byte。如果最后没数据了,Next函数最后返回io.EOF。 ##drive.RowsAffected @@ -156,30 +160,30 @@ Value的值必须所有的驱动里面控制的,Value要么是nil,要么是 time.Time ##drive.ValueConverter -ValueConverter接口定义了如何把一个普通的值转化成drive.Value的接口 +ValueConverter接口定义了如何把一个普通的值转化成driver.Value的接口 type ValueConverter interface { ConvertValue(v interface{}) (Value, error) } -ValueConverter对于各种各种的值的实现必须保持高度的一致性,在驱动包里面很多地方会使用到这个转化接口 +在开发的数据库驱动包里面实现这个接口的函数在很多地方会使用到,这个ValueConverter有很多好处: - 转化drive.value到数据库表相应的字段,例如int64的数据如何转化成数据库表uint16字段 - 把数据库查询结果转化成drive.Value值 -- 在scan函数里面如何吧dirve.Value值转化成用户定义的值 +- 在scan函数里面如何把dirve.Value值转化成用户定义的值 ##drive.Valuer -Valuer接口定义了返回如何返回一个drive.Value值 +Valuer接口定义了返回一个driver.Value的方式 type Valuer interface { Value() (Value, error) } -很多类型上面都定义了这个Value方法,用来实现每个相应类型如何转化为drive.Value类型。 +很多类型都实现了这个Value方法,用来自身与driver.Value的转化。 -通过上面的讲解,对于驱动的开发有了细致的了解,一个驱动基本上就是实现上面的这些接口就能完成我们平常的增删改所有的操作了,底层就是和相应的数据库进行数据交互就可以了。 +通过上面的讲解,你应该对于驱动的开发有了一个基本的了解,一个驱动只要实现了这些接口就能完成增删查改等基本操作了,剩下的就是与相应的数据库进行数据交互等细节问题了,在此不再赘述。 ##database/sql -database/sql里面定义了基于这个驱动之上的一些方法,这些方法都是基于drive接口来封装的,同时内部还实现了一个建议的conn pool。 +database/sql在database/sql/driver提供的接口基础上定义了一些更高阶的方法,用以简化数据库操作,同时内部还实现了一个建议的conn pool。 type DB struct { driver driver.Driver @@ -189,7 +193,7 @@ database/sql里面定义了基于这个驱动之上的一些方法,这些方 closed bool } -我们可以看到Open函数返回的是DB对象,里面有一个freeConn,这个就是那个简易的连接池。它的实现也是就是很简单,当执行Db.prepare的时候最后会defer:`db.putConn(ci, err)`,也就是放入连接池,而每次调用conn的时候也会优先判断freeConn的长度是否大于0,大于0说明有使用过的conn,直接拿出来就用了。 +我们可以看到Open函数返回的是DB对象,里面有一个freeConn,,它就是那个简易的连接池。它的实现相当简单或者说简陋,就是当执行Db.prepare的时候会defer:db.putConn(ci, err),也就是放入连接池,每次调用conn的时候会先判断freeConn的长度是否大于0,大于0说明有可以复用的conn,直接拿出来用就是了,如果不大于0,则创建一个conn,然后再返回之。 ## links