真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Go語(yǔ)言開發(fā)(十七)、Go語(yǔ)言database/sql接口

Go語(yǔ)言開發(fā)(十七)、Go語(yǔ)言database/sql接口

一、database/sql接口

Go語(yǔ)言官方?jīng)]有提供數(shù)據(jù)庫(kù)驅(qū)動(dòng),而是為開發(fā)數(shù)據(jù)庫(kù)驅(qū)動(dòng)定義了標(biāo)準(zhǔn)接口database/sql,開發(fā)者可以根據(jù)database/sql接口來(lái)開發(fā)相應(yīng)的數(shù)據(jù)庫(kù)驅(qū)動(dòng),只要是按照標(biāo)準(zhǔn)接口database/sql開發(fā)的代碼,以后需要遷移數(shù)據(jù)庫(kù)時(shí),不需要任何修改。

創(chuàng)新互聯(lián)專注于瀾滄企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城網(wǎng)站制作。瀾滄網(wǎng)站建設(shè)公司,為瀾滄等地區(qū)提供建站服務(wù)。全流程按需制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

二、database/sql常用接口

1、sql.Register

sql.Register函數(shù)用來(lái)注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng),第三方開發(fā)者開發(fā)數(shù)據(jù)庫(kù)驅(qū)動(dòng)時(shí),會(huì)在init函數(shù)內(nèi)調(diào)用sql.Register完成本驅(qū)動(dòng)的注冊(cè)。

func Register(name string, driver driver.Driver) {
   driversMu.Lock()
   defer driversMu.Unlock()
   if driver == nil {
      panic("sql: Register driver is nil")
   }
   if _, dup := drivers[name]; dup {
      panic("sql: Register called twice for driver " + name)
   }
   drivers[name] = driver
}

Go-SQL-Driver/MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)的實(shí)現(xiàn)如下:

func init() {
   sql.Register("mysql", &MySQLDriver{})
}

第三方數(shù)據(jù)庫(kù)驅(qū)動(dòng)通常通過(guò)調(diào)用sql.Register函數(shù)來(lái)注冊(cè)自己的數(shù)據(jù)庫(kù)驅(qū)動(dòng)名稱以及相應(yīng)的driver實(shí)現(xiàn)。在database/sql內(nèi)部通過(guò)一個(gè)map來(lái)存儲(chǔ)用戶定義的相應(yīng)驅(qū)動(dòng)。
var drivers = make(map[string]driver.Driver)

2、driver.Driver

Driver是一個(gè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的接口,定義了一個(gè)Open(name string)方法,返回一個(gè)數(shù)據(jù)庫(kù)的Conn接口。

type Driver interface {
      Open(name string) (Conn, error)
}

Conn只能用來(lái)進(jìn)行一次goroutine操作,即Conn應(yīng)用于多個(gè)goroutine。
第三方驅(qū)動(dòng)都會(huì)實(shí)現(xiàn)driver.Driver接口,Open方法會(huì)解析name參數(shù)來(lái)獲取相關(guān)數(shù)據(jù)庫(kù)的連接信息,解析完成后,使用此連接信息來(lái)初始化一個(gè)Conn并返回。

3、driver.Conn

driver.Conn是一個(gè)數(shù)據(jù)庫(kù)連接的接口,定義了一系列方法,Conn只能應(yīng)用在一個(gè)goroutine中,不能使用在多個(gè)goroutine中。

type Conn interface {
   Prepare(query string) (Stmt, error)
   Close() error
   Begin() (Tx, error)
}

Prepare函數(shù)返回與當(dāng)前連接相關(guān)的執(zhí)行Sql語(yǔ)句的準(zhǔn)備狀態(tài),可以進(jìn)行查詢、刪除等操作。
Close函數(shù)關(guān)閉當(dāng)前的連接,執(zhí)行釋放連接擁有的資源等清理工作。通常第三方數(shù)據(jù)庫(kù)驅(qū)動(dòng)實(shí)現(xiàn)了database/sql建議的連接池,開發(fā)者不必去實(shí)現(xiàn)緩存連接。
Begin函數(shù)返回一個(gè)代表事務(wù)處理的Tx,通過(guò)Tx可以進(jìn)行查詢、更新等操作或者對(duì)事務(wù)進(jìn)行回滾、遞交。

4、driver.Stmt

driver.Stmt是一種準(zhǔn)備好的狀態(tài),與Conn相關(guān)聯(lián),而且只能應(yīng)用于一個(gè)goroutine中,不能應(yīng)用于多個(gè)goroutine。

type Stmt interface {
   Close() error

   NumInput() int
   Exec(args []Value) (Result, error)
   Query(args []Value) (Rows, error)
}

Close函數(shù)關(guān)閉當(dāng)前的連接狀態(tài),但如果當(dāng)前正在執(zhí)行query,query還是有效返回rows數(shù)據(jù)。
NumInput函數(shù)返回當(dāng)前預(yù)留參數(shù)的個(gè)數(shù),當(dāng)返回>=0時(shí)數(shù)據(jù)庫(kù)驅(qū)動(dòng)就會(huì)智能檢查調(diào)用者的參數(shù)。當(dāng)數(shù)據(jù)庫(kù)驅(qū)動(dòng)包不知道預(yù)留參數(shù)的時(shí)候,返回-1。
Exec函數(shù)執(zhí)行Prepare準(zhǔn)備好的sql,傳入?yún)?shù)執(zhí)行update/insert等操作,返回Result數(shù)據(jù)
Query函數(shù)執(zhí)行Prepare準(zhǔn)備好的sql,傳入需要的參數(shù)執(zhí)行select操作,返回Rows結(jié)果集

5、driver.Tx

driver.Tx是事務(wù)接口,包含Commit、Rollback方法,數(shù)據(jù)庫(kù)驅(qū)動(dòng)只需實(shí)現(xiàn)Commit、Rollback函數(shù)即可。

type Tx interface {
   Commit() error
   Rollback() error
}

Go-SQL-Driver/MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)的實(shí)現(xiàn)如下:

type mysqlTx struct {
   mc *mysqlConn
}

func (tx *mysqlTx) Commit() (err error) {
   if tx.mc == nil || tx.mc.closed.IsSet() {
      return ErrInvalidConn
   }
   err = tx.mc.exec("COMMIT")
   tx.mc = nil
   return
}

func (tx *mysqlTx) Rollback() (err error) {
   if tx.mc == nil || tx.mc.closed.IsSet() {
      return ErrInvalidConn
   }
   err = tx.mc.exec("ROLLBACK")
   tx.mc = nil
   return
}

6、driver.Execer

driver.Execer是一個(gè)Conn可選擇實(shí)現(xiàn)的接口。

type Execer interface {
   Exec(query string, args []Value) (Result, error)
}

如果第三方數(shù)據(jù)庫(kù)驅(qū)動(dòng)沒(méi)有實(shí)現(xiàn)driver.Execer接口,調(diào)用DB.Exec會(huì)首先調(diào)用Prepare返回Stmt,然后執(zhí)行Stmt的Exec,然后關(guān)閉Stmt。

7、driver.Result

driver.Result是執(zhí)行Update/Insert等操作返回的結(jié)果接口。

type Result interface {
   LastInsertId() (int64, error)
   RowsAffected() (int64, error)
}

LastInsertId函數(shù)返回由數(shù)據(jù)庫(kù)執(zhí)行插入操作得到的自增ID號(hào)。
RowsAffected函數(shù)返回query操作影響的數(shù)據(jù)條目數(shù)。

8、driver.Rows

driver.Rows是執(zhí)行查詢返回的結(jié)果集接口。

type Rows interface {
   Columns() []string
   Close() error
   Next(dest []Value) error
}

Columns函數(shù)返回查詢數(shù)據(jù)庫(kù)表的字段信息,這個(gè)返回的slice和sql查詢的字段一一對(duì)應(yīng),而不是返回整個(gè)表的所有字段。
Close函數(shù)用來(lái)關(guān)閉Rows迭代器。
Next函數(shù)用來(lái)返回下一條數(shù)據(jù),把數(shù)據(jù)賦值給dest。dest里面的元素必須是driver.Value的值除了string,返回的數(shù)據(jù)里面所有的string都必須要轉(zhuǎn)換成[]byte。如果最后沒(méi)數(shù)據(jù)了,Next函數(shù)最后返回io.EOF。

9、driver.RowsAffected

driver.RowsAffected是int64的別名,但實(shí)現(xiàn)了Result接口,用來(lái)底層實(shí)現(xiàn)Result的表示方式。

type RowsAffected int64

var _ Result = RowsAffected(0)

func (RowsAffected) LastInsertId() (int64, error) {
   return 0, errors.New("no LastInsertId available")
}

func (v RowsAffected) RowsAffected() (int64, error) {
   return int64(v), nil
}

10、driver.Value

driver.Value是空接口,是數(shù)據(jù)庫(kù)驅(qū)動(dòng)必須能夠操作的Value,Value可以是nil,int64,float64,bool,[]bytestring,time.Time。
type Value interface{}

11、driver.ValueConverter

driver.ValueConverter接口定義了如何把一個(gè)普通的值轉(zhuǎn)化成driver.Value的接口

type ValueConverter interface {
   // ConvertValue converts a value to a driver Value.
   ConvertValue(v interface{}) (Value, error)
}

driver.ValueConverter接口實(shí)現(xiàn)如下:

type stringType struct{}

func (stringType) ConvertValue(v interface{}) (Value, error) {
   switch v.(type) {
   case string, []byte:
      return v, nil
   }
   return fmt.Sprintf("%v", v), nil
}

數(shù)據(jù)庫(kù)驅(qū)動(dòng)開發(fā)中,ConvertValue方法用途廣泛:
(1)轉(zhuǎn)化driver.value到數(shù)據(jù)庫(kù)表相應(yīng)的字段,例如int64的數(shù)據(jù)如何轉(zhuǎn)化成數(shù)據(jù)庫(kù)表uint16字段。
(2)把數(shù)據(jù)庫(kù)查詢結(jié)果轉(zhuǎn)化成driver.Value值
(3)在scan函數(shù)里面如何把driver.Value值轉(zhuǎn)化成用戶定義的值

12、driver.Valuer

driver.Valuer接口定義一個(gè)返回driver.Value的方法。

type Valuer interface {
   // Value returns a driver Value.
   Value() (Value, error)
}

13、sql.Open

func Open(driverName, dataSourceName string) (*DB, error) {
   driversMu.RLock()
   driveri, ok := drivers[driverName]
   driversMu.RUnlock()
   if !ok {
      return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
   }

   if driverCtx, ok := driveri.(driver.DriverContext); ok {
      connector, err := driverCtx.OpenConnector(dataSourceName)
      if err != nil {
         return nil, err
      }
      return OpenDB(connector), nil
   }

   return OpenDB(dsnConnector{dsn: dataSourceName, driver: driveri}), nil
}

Open函數(shù)返回DB對(duì)象,

type DB struct {
   connector driver.Connector
   numClosed uint64

   mu           sync.Mutex // protects following fields
   freeConn     []*driverConn
   connRequests map[uint64]chan connRequest
   nextRequest  uint64 // Next key to use in connRequests.
   numOpen      int    // number of opened and pending open connections
   openerCh    chan struct{}
   resetterCh  chan *driverConn
   closed      bool
   dep         map[finalCloser]depSet
   lastPut     map[*driverConn]string // stacktrace of last conn's put; debug only
   maxIdle     int                    // zero means defaultMaxIdleConns; negative means 0
   maxOpen     int                    // <= 0 means unlimited
   maxLifetime time.Duration          // maximum amount of time a connection may be reused
   cleanerCh   chan struct{}

   stop func() // stop cancels the connection opener and the session resetter.
}

freeConn是簡(jiǎn)易的連接池。當(dāng)執(zhí)行db.prepare?->?db.prepareDC時(shí)會(huì)defer dc.releaseConn,然后調(diào)用db.putConn,把連接放入連接池,每次調(diào)用db.conn的時(shí)候會(huì)先判斷freeConn的長(zhǎng)度是否大于0,大于0說(shuō)明有可以復(fù)用的conn,如果不大于0,則創(chuàng)建一個(gè)conn,然后返回。


新聞名稱:Go語(yǔ)言開發(fā)(十七)、Go語(yǔ)言database/sql接口
URL鏈接:http://weahome.cn/article/peggjs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部