參考:https://studygolang.com/pkgdocgolang
1》導入方式:sql
import "database/sql/driver"
driver包定義了應被數據庫驅動實現的接口,這些接口會被sql包使用。 數據庫
絕大多數代碼應使用sql包。緩存
2》driver.Driver - 在database/sql/driver中函數
Driver是一個數據庫驅動的接口,其定義了一個Open(name string)方法,該方法返回一個數據庫的Conn接口:ui
type Driver interface { // Open返回一個新的與數據庫的鏈接,參數name的格式是驅動特定的。 // // Open可能返回一個緩存的鏈接(以前關閉的鏈接),但這麼作是沒必要要的; // sql包會維護閒置鏈接池以便有效的重用鏈接。 // // 返回的鏈接同一時間只會被一個go程使用。 Open(name string) (Conn, error) }
由於返回的鏈接同一時間只會被一個go程使用,因此返回的Conn只能用來進行一次goroutine操做,即不能把這個Conn應用於Go的多個goroutine中,不然會出現錯誤,如:
spa
go goroutineA(Conn) //執行查詢操做 go goroutineB(Conn) //執行插入操做
這樣的代碼會使Go不知某個操做究竟是由哪一個goroutine發起的從而致使數據混亂。便可能會講goroutineA裏面執行的查詢操做的結果返回給goroutineB,從而讓goroutineB將此結果當成本身執行的插入數據
code
3》driver.Conn - 在database/sql/driver中blog
Conn是一個數據鏈接的接口定義。這個Conn只能應用在一個goroutine中,如上所說。接口
type Conn interface { // Prepare返回一個準備好的、綁定到該鏈接的狀態。 Prepare(query string) (Stmt, error) // Close做廢並中止任何如今準備好的狀態和事務,將該鏈接標註爲再也不使用。 // // 由於sql包維護着一個鏈接池,只有當閒置鏈接過剩時纔會調用Close方法, // 驅動的實現中不須要添加本身的鏈接緩存池。 Close() error // Begin開始並返回一個新的事務。 Begin() (Tx, error) }
Prepare函數返回與當前鏈接相關的SQL語句的準備狀態,能夠進行查詢、刪除等操做
Close函數關閉當前的鏈接,執行釋放鏈接擁有的資源等清理工做。由於驅動實現了database/sql中建議的conn pool,因此不用再去實現緩存conn之類的,這樣會更容易引發問題
Begin函數返回一個表明事務處理的Tx,經過它你能夠進行查詢、更新等操做,或者對事務進行回滾、遞交
4》driver.Stmt - 在database/sql/driver中
Stmt是一種準備好的狀態,綁定到一個Conn中,並只能應用在一個goroutine中。
type Stmt interface { // Close關閉Stmt。 // // 和Go1.1同樣,若是Stmt被任何查詢使用中的話,將不會被關閉。 Close() error // NumInput返回佔位參數的個數。 // // 若是NumInput返回值 >= 0,sql包會提早檢查調用者提供的參數個數, // 而且會在調用Exec或Query方法前返回數目不對的錯誤。 // // NumInput能夠返回-1,若是驅動佔位參數的數量不知時。 // 此時sql包不會提早檢查參數個數。 NumInput() int // Exec執行查詢,而不會返回結果,如insert或update。 Exec(args []Value) (Result, error) // Query執行查詢並返回結果,如select。 Query(args []Value) (Rows, error) }
Close函數關閉當前的鏈接狀態,可是若是當前正在執行query,query仍是會有效地返回rows數據
Exec函數執行Conn的Prepare準備好的sql,傳入參數執行update/insert等操做,返回Result數據
Query函數執行Conn的Prepare準備好的sql,傳入須要的參數執行select操做,返回Rows結果集
5》driver.Tx - 在database/sql/driver中
事務處理通常就兩個過程,遞交或回滾,即下面的兩個函數:
type Tx interface { Commit() error Rollback() error }
6》driver.Execer - 在database/sql/driver中
這是一個Conn可選擇實現的接口
type Execer interface { Exec(query string, args []Value) (Result, error) }
若是一個Conn未實現Execer接口,sql包的DB.Exec會首先準備一個查詢(即調用Prepare返回Stmt),執行狀態(即執行Stmt的Exec函數),而後關閉狀態(即關閉Stmt)。Exec可能會返回ErrSkip。
7》driver.Result
這是是執行Update/insert等操做返回的結果接口定義
type Result interface { // LastInsertId返回insert等命令後數據庫自動生成的ID LastInsertId() (int64, error) // RowsAffected返回被查詢影響的行數 RowsAffected() (int64, error) }
8》driver.Rows
Rows是執行查詢返回的結果集接口定義
type Rows interface { // Columns返回各列的名稱,列的數量能夠從切片長度肯定。 // 若是某個列的名稱未知,對應的條目應爲空字符串。 Columns() []string // Close關閉Rows。 Close() error // 調用Next方法以將下一行數據填充進提供的切片中,即返回下一條數據,並把數據返回給dest。 // 提供的切片必須和Columns返回的切片長度相同。 // // 切片dest可能被填充同一種驅動Value類型,但字符串除外;即dest裏面的元素必須是driver.Vlaue的值,除了string。 // 全部string值都必須轉換爲[]byte。 // // 當沒有更多行時,Next應返回io.EOF。 Next(dest []Value) error }
Columns函數返回查詢數據庫表的字段信息,返回的slice和sql查詢的字段一一對應,而不是返回整個表的全部字段
9》driver.RowsAffected
type RowsAffected int64
RowsAffected其實就是int64的別名,可是它實現了Result接口,用來底層實現Result的表示方式
RowsAffected實現了Result接口,用於insert或update操做,這些操做會修改零到多行數據。
func (RowsAffected) LastInsertId() (int64, error)
func (v RowsAffected) RowsAffected() (int64, error)
10》driver.Value
type Value interface{}
Value其實就是一個空接口,它能夠容納任何數據
driver.Value是驅動必須可以操做的Value,因此Value要麼是nil,要麼是下面的任意一種:
int64
float64
bool []byte string [*] Rows.Next不會返回該類型值 time.Time
11》driver.ValueConverter
ValueConverter接口定義了一個如何把一個普通值轉化成driver.Value的接口
type ValueConverter interface { // ConvertValue將一個值轉換爲驅動支持的Value類型 ConvertValue(v interface{}) (Value, error) }
ValueConverter接口提供了ConvertValue方法。
driver包提供了各類ValueConverter接口的實現,以保證不一樣驅動之間的實現和轉換的一致性。ValueConverter接口有以下用途:
12》driver.Valuer
type Valuer interface { // Value返回一個驅動支持的Value類型值 Value() (Value, error) }
Valuer接口定義了一個返回driver.Value的方法
不少類型都實現了這個Value方法,用來實現自身與driver.Value的轉換
13》ColumnConverter
type ColumnConverter interface { // ColumnConverter返回指定列的ValueConverter // 若是該列未指定類型,或不該特殊處理,應返回DefaultValueConverter ColumnConverter(idx int) ValueConverter }
若是Stmt有本身的列類型,能夠實現ColumnConverter接口,返回值能夠將任意類型轉換爲驅動的Value類型。
14》變量
1.Bool
var Bool boolType
Bool是ValueConverter接口值,用於將輸入的值轉換爲布爾類型。使用方式爲driver.Bool(1),會返回true
轉換規則以下:
- 布爾類型:不作修改 - 整數類型: 1 爲真 0 爲假 其他整數會致使錯誤 - 字符串和[]byte:與strconv.ParseBool的規則相同 - 全部其餘類型都會致使錯誤
其實現源碼爲:
var Bool boolType type boolType struct{} var _ ValueConverter = boolType{} func (boolType) String() string { return "Bool" } func (boolType) ConvertValue(src interface{}) (Value, error) { switch s := src.(type) { //首先查看輸入的src值的類型 case bool: //若是輸入的是bool類型,則直接輸出便可 return s, nil case string: //若是是其餘類型,則要將其轉成Bool類型 b, err := strconv.ParseBool(s) if err != nil { return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s) } return b, nil case []byte: b, err := strconv.ParseBool(string(s)) if err != nil { return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s) } return b, nil } //除了上面的幾種類型,若是是下面的類型,只有當其值爲1或0時可以將其轉成bool類型 sv := reflect.ValueOf(src) switch sv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: iv := sv.Int() if iv == 1 || iv == 0 { return iv == 1, nil } return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: uv := sv.Uint() if uv == 1 || uv == 0 { return uv == 1, nil } return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv) } //除了上面的類型,若是輸入的src是其餘的類型,則會報錯 return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src) }
2.Int32
var Int32 int32Type
Int32是一個ValueConverter接口值,用於將值轉換爲int64類型,會尊重int32類型的限制。
3.String
var String stringType
String是一個ValueConverter接口值,用於將值轉換爲字符串。若是值v是字符串或者[]byte類型,不會作修改,若是值v是其它類型,會轉換爲fmt.Sprintf("%v", v)。
4.DefaultParameterConverter
var DefaultParameterConverter defaultConverter
DefaultParameterConverter是ValueConverter接口的默認實現,當一個Stmt沒有實現ColumnConverter時,就會使用它。
若是值value知足函數IsValue(value)爲真,DefaultParameterConverter直接返回 value。不然,整數類型會被轉換爲int64,浮點數轉換爲float64,字符串轉換爲[]byte。其它類型會致使錯誤。
5.ResultNoRows
var ResultNoRows noRows
ResultNoRows是預約義的Result類型值,用於當一個DDL命令(如create table)成功時被驅動返回。它的LastInsertId和RowsAffected方法都返回錯誤。
舉例:
package main import( "fmt" "reflect" "time" "database/sql/driver" ) type valueConverterTest struct { c driver.ValueConverter in interface{} out interface{} err string } var now = time.Now() var answer int64 = 42 type ( i int64 f float64 b bool bs []byte s string t time.Time is []int ) var valueConverterTests = []valueConverterTest{ {driver.Bool, "true", true, ""}, {driver.Bool, "True", true, ""}, {driver.Bool, []byte("t"), true, ""}, {driver.Bool, true, true, ""}, {driver.Bool, "1", true, ""}, {driver.Bool, 1, true, ""}, {driver.Bool, int64(1), true, ""}, {driver.Bool, uint16(1), true, ""}, {driver.Bool, "false", false, ""}, {driver.Bool, false, false, ""}, {driver.Bool, "0", false, ""}, {driver.Bool, 0, false, ""}, {driver.Bool, int64(0), false, ""}, {driver.Bool, uint16(0), false, ""}, {c: driver.Bool, in: "foo", err: "sql/driver: couldn't convert \"foo\" into type bool"}, {c: driver.Bool, in: 2, err: "sql/driver: couldn't convert 2 into type bool"}, {driver.DefaultParameterConverter, now, now, ""}, {driver.DefaultParameterConverter, (*int64)(nil), nil, ""}, {driver.DefaultParameterConverter, &answer, answer, ""}, {driver.DefaultParameterConverter, &now, now, ""}, {driver.DefaultParameterConverter, i(9), int64(9), ""}, {driver.DefaultParameterConverter, f(0.1), float64(0.1), ""}, {driver.DefaultParameterConverter, b(true), true, ""}, {driver.DefaultParameterConverter, bs{1}, []byte{1}, ""}, {driver.DefaultParameterConverter, s("a"), "a", ""}, {driver.DefaultParameterConverter, is{1}, nil, "unsupported type main.is, a slice of int"}, } func main() { for i, tt := range valueConverterTests { out, err := tt.c.ConvertValue(tt.in) goterr := "" if err != nil { goterr = err.Error() } if goterr != tt.err { fmt.Printf("test %d: %T(%T(%v)) error = %q; want error = %q\n", i, tt.c, tt.in, tt.in, goterr, tt.err) } if tt.err != "" { continue } if !reflect.DeepEqual(out, tt.out) { fmt.Printf("test %d: %T(%T(%v)) = %v (%T); want %v (%T)\n", i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out) } } }
6.錯誤ErrBadConn
var ErrBadConn = errors.New("driver: bad connection")
ErrBadConn應被驅動返回,以通知sql包一個driver.Conn處於損壞狀態(如服務端以前關閉了鏈接),sql包會重啓一個新的鏈接。
爲了不重複的操做,若是數據庫服務端執行了操做,就不該返回ErrBadConn。即便服務端返回了一個錯誤。
7.錯誤ErrSkip
var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")
ErrSkip可能會被某些可選接口的方法返回,用於在運行時代表快速方法不可用,sql包應像未實現該接口的狀況同樣執行。ErrSkip只有文檔顯式說明的地方纔支持,如driver.Execer。
15》其餘函數
func IsValue(v interface{}) bool
IsValue報告v是不是合法的Value類型參數。和IsScanValue不一樣,IsValue接受字符串類型。
func IsScanValue(v interface{}) bool
IsScanValue報告v是不是合法的Value掃描類型參數。和IsValue不一樣,IsScanValue不接受字符串類型。