青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

牽著老婆滿街逛

嚴以律己,寬以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

Golang操作數據庫

轉載自:http://www.cnblogs.com/hupengcool/p/4143238.html

基本概念

  • Open() – creates a DB
  • Close() - closes the DB
  • Query() - 查詢
  • QueryRow() -查詢行
  • Exec() -執行操作,update,insert,delete
  • Row - A row is not a hash map, but an abstraction of a cursor
  • Next()
  • Scan()

注意:DB并不是指的一個connection

連接到數據庫

我們以mysql為例,使用github.com/go-sql-driver/mysql,首先我們需要導入我們需要的包

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

注意我們導入github.com/go-sql-driver/mysql 前面用了一個"_",_操作其實是引入該包,而不直接使用包里面的函數,而是調用了該包里面的init函數,import的時候其實是執行了該包里面的init函數,初始化了里面的變量,_操作只是說該包引入了,我只初始化里面的 init函數和一些變量,但是往往這些init函數里面是注冊自己包里面的引擎,讓外部可以方便的使用,就很多實現database/sql的包,在 init函數里面都是調用了sql.Register(name string, driver driver.Driver)注冊自己,然后外部就可以使用了。

我們用Open()函數來打開一個database handle

db, err := sql.Open("mysql", "user:password@tcp(ip:port)/database")

寫一個完整的:

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "log"
)
func main() {
    db, err := sql.Open("mysql""user:password@tcp(ip:port)/database")
    if err != nil {
        log.Println(err)
    }
    
    //在這里進行一些數據庫操作
    
    defer db.Close()
}

我們在執行Open函數的時候,并不會去獲得數據庫連接有效性,當執行數據庫操作的時候才會去連接,當我們需要在Open之后就知道連接的有效性的時候,可以通過Ping()來進行

err = db.Ping()
if err != nil {
    log.Println(err)
}

我們通常習慣使用Close來關閉數據庫連接,但是sql.DB是被設計成長期有效的類型,我們不應該頻繁的Open和Close,相反,我們應該建立一個sql.DB,在程序需要進行數據庫操作的時候一直使用它,不要在一個方法里面進行Open和Close,應該把sql.DB作為參數傳遞給方法

進行數據庫操作

增刪改操作

Exec()方法一般用于增刪改操作,這里以增加為例:

stmt, err := db.Prepare("insert into user(name,age)values(?,?)")
if err != nil {
    log.Println(err)
}

rs, err := stmt.Exec("go-test", 12)
if err != nil {
    log.Println(err)
}
//我們可以獲得插入的id
id, err := rs.LastInsertId()
//可以獲得影響行數
affect, err := rs.RowsAffected()


查詢操作

一般的查詢
var name string
    var age int
    rows, err := db.Query("select name,age from user where id = ? ", 1)
    if err != nil {
        fmt.Println(err)
    }
    defer rows.Close()

    for rows.Next() {
        err := rows.Scan(&name, &age)
        if err != nil {
            fmt.Println(err)
        }
    }

    err = rows.Err()
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println("name:", url, "age:", description)
我們應該養成關閉rows的習慣,在任何時候,都不要忘記rows.Close().哪怕這個rows在確實循環完之后,已經自動關閉掉了,我們定義rows.Close()也是對我們沒有壞處的,因為我們無法保證,rows是否會正常的循環完。

查詢單條記錄,

我們使用db.QueryRow()

var name string
    err = db.QueryRow("select name from user where id = ?", 222).Scan(&name)

沒有結果的時候會返回err

處理空值

我們用一個name字段為空的記錄來舉例

var name NullString
err := db.QueryRow("SELECT name FROM names WHERE id = ?", id).Scan(&name)

if name.Valid {
        // use name.String
else {
        // value is NULL
}

在這種情況下我們通常使用NullString,但是有時候我們并不關心值是不是Null,我們只需要吧他當一個空字符串來對待就行。這時候我們可以使用[]byte(null byte[]可以轉化為空string) 或者 sql.RawBytes,

var col1, col2 []byte

for rows.Next() {
    // Scan the value to []byte
    err = rows.Scan(&col1, &col2)

    if err != nil {
        panic(err.Error()) // Just for example purpose. You should use proper error handling instead of panic
    }

    // Use the string value
    fmt.Println(string(col1), string(col2))
}

使用*sql.RawBytes

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    // Open database connection
    db, err := sql.Open("mysql""user:password@/dbname")
    if err != nil {
        panic(err.Error())  // Just for example purpose. You should use proper error handling instead of panic
    }
    defer db.Close()

    // Execute the query
    rows, err := db.Query("SELECT * FROM table")
    if err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }

    // Get column names
    columns, err := rows.Columns()
    if err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }

    // Make a slice for the values
    values := make([]sql.RawBytes, len(columns))

    // rows.Scan wants '[]interface{}' as an argument, so we must copy the
    // references into such a slice
    // See http://code.google.com/p/go-wiki/wiki/InterfaceSlice for details
    scanArgs := make([]interface{}, len(values))
    for i := range values {
        scanArgs[i] = &values[i]
    }

    // Fetch rows
    for rows.Next() {
        // get RawBytes from data
        err = rows.Scan(scanArgs)
        if err != nil {
            panic(err.Error()) // proper error handling instead of panic in your app
        }

        // Now do something with the data.
        // Here we just print each column as a string.
        var value string
        for i, col := range values {
            // Here we can check if the value is nil (NULL value)
            if col == nil {
                value = "NULL"
            } else {
                value = string(col)
            }
            fmt.Println(columns[i], "", value)
        }
        fmt.Println("-----------------------------------")
    }
    if err = rows.Err(); err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }
}


事務

使用db.Begin()來開啟一個事務, 通過Commit()和Rollback()方法來關閉。

tx := db.Begin()
tx.Rollback()
tx.Commit()

Exec, Query, QueryRow and Prepare 方法已經全部可以在tx上面使用。使用方法和在*sql.DB是一樣的,事務必須以Commit()或者Rollback()結束

The Connection Pool

在database/sql中有一個很基本的連接池,你并沒有多大的控制權,僅僅可以設置SetMaxIdleConns和SetMaxOpenConns,也就是最大空閑連接和最大連接數。

    db.SetMaxIdleConns(n)
    db.SetMaxOpenConns(n)

posted on 2016-12-23 10:52 楊粼波 閱讀(347) 評論(0)  編輯 收藏 引用

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美在线观看视频一区二区| 国产丝袜美腿一区二区三区| 一本久道久久综合狠狠爱| 欧美成人精品在线播放| 免费91麻豆精品国产自产在线观看| 久久久久久色| 久久精品电影| 米奇777在线欧美播放| 免费观看欧美在线视频的网站| 老巨人导航500精品| 欧美11—12娇小xxxx| 欧美福利一区二区| 亚洲美女中出| 午夜综合激情| 欧美成人免费在线视频| 欧美日韩国产一级| 国产农村妇女毛片精品久久麻豆 | 久久精品av麻豆的观看方式| 久久精品国产一区二区电影| 欧美成人网在线| 国产精品视频免费观看| 亚洲二区免费| 欧美一区二区免费观在线| 久久综合色播五月| 日韩一级网站| 免费成人你懂的| 国产日本亚洲高清| 一区二区成人精品 | 亚洲精品一区二区三区樱花| 亚洲欧美激情四射在线日| 美女久久一区| 国产午夜精品视频免费不卡69堂| 亚洲欧洲精品一区二区精品久久久| 亚洲欧美日韩国产综合| 欧美激情网站在线观看| 午夜久久电影网| 欧美三级中文字幕在线观看| 在线播放日韩| 久久福利毛片| 亚洲图片在线| 欧美日韩精品不卡| 91久久精品www人人做人人爽 | 久久久久久网站| 国产精品婷婷午夜在线观看| 国产精品国产三级国产普通话蜜臀| 亚洲夫妻自拍| 久久欧美中文字幕| 亚洲一区免费在线观看| 欧美日韩免费看| 日韩视频免费大全中文字幕| 欧美va天堂在线| 久久九九热免费视频| 国产亚洲精品高潮| 欧美在线在线| 午夜精品久久| 国产一区二区三区在线观看精品| 欧美一区二区三区在| 亚洲视频专区在线| 国产精品区二区三区日本| 亚洲一区在线看| 中文在线资源观看网站视频免费不卡 | av成人免费在线观看| 欧美日韩福利在线观看| 亚洲少妇最新在线视频| 在线亚洲电影| 国产欧美丝祙| 巨胸喷奶水www久久久免费动漫| 欧美中日韩免费视频| 黑人巨大精品欧美一区二区小视频| 久久久久久97三级| 久久频这里精品99香蕉| 最新日韩精品| 亚洲午夜国产一区99re久久| 国产九九精品视频| 久久亚洲国产精品一区二区| 久久露脸国产精品| 99综合精品| 午夜精品久久久久久久久久久| 国产亚洲制服色| 亚洲电影在线| 欧美精品一二三| 午夜精品短视频| 久久免费观看视频| 99re热精品| 亚洲欧美日韩视频一区| 亚洲国产精品悠悠久久琪琪| 91久久精品日日躁夜夜躁国产| 欧美日韩中文在线观看| 久久av老司机精品网站导航| 老司机免费视频一区二区| 在线中文字幕一区| 久久久久久久91| 亚洲一区观看| 久久午夜激情| 亚洲欧美在线观看| 老鸭窝毛片一区二区三区| 亚洲欧美激情视频在线观看一区二区三区| 亚洲欧美国产一区二区三区| 亚洲国产日本| 亚洲欧美成人精品| 亚洲精品视频免费| 日韩视频免费看| 久久久久久成人| 亚洲国产成人91精品| 亚洲视频免费在线观看| 在线不卡中文字幕| 亚洲一区三区在线观看| 亚洲精品一区二区三区福利| 亚洲欧美视频一区| 中文日韩欧美| 欧美成人精品在线| 久久在线观看视频| 国产精品日韩久久久| 亚洲欧洲一区二区天堂久久| 国产香蕉久久精品综合网| 亚洲肉体裸体xxxx137| 国内自拍亚洲| 亚洲一区中文| 亚洲一区日韩| 欧美精品色综合| 欧美成人一区二区三区| 国产一区二区观看| 亚洲欧美综合| 午夜日韩在线| 国产精品a级| 亚洲精品视频中文字幕| 91久久线看在观草草青青| 久久se精品一区二区| 久久精品成人一区二区三区| 国产精品午夜国产小视频| 一区二区三区成人| 亚洲香蕉网站| 国产精品免费看片| 亚洲一区中文| 久久精品电影| 国内一区二区三区| 久久久久国内| 欧美成人综合网站| 亚洲国产精品久久久| 另类天堂av| 亚洲国产欧美一区二区三区同亚洲| 亚洲欧洲精品天堂一级| 欧美黄色aa电影| av成人免费在线| 香蕉久久夜色精品国产| 国产日韩精品视频一区| 欧美一级艳片视频免费观看| 麻豆精品网站| 日韩视频在线你懂得| 欧美日韩在线观看一区二区三区| 一本到12不卡视频在线dvd| 亚洲欧美中文字幕| 国产一区清纯| 欧美电影免费观看高清| 99热精品在线| 久久精品30| 91久久国产综合久久蜜月精品| 欧美精品导航| 亚洲免费影视| 欧美岛国激情| 亚洲在线播放| 狠狠色丁香婷婷综合影院| 欧美国产日韩二区| 中文在线一区| 欧美二区在线播放| 亚洲女人天堂av| 激情小说亚洲一区| 欧美日韩国产影片| 欧美在线日韩在线| 亚洲全部视频| 久久九九电影| 国产精品99久久久久久久久| av成人免费观看| 99xxxx成人网| 国产亚洲人成网站在线观看| 噜噜噜久久亚洲精品国产品小说| 亚洲人成亚洲人成在线观看| 亚洲欧美怡红院| 亚洲精品久久嫩草网站秘色 | 久久精品欧美| 99国产精品视频免费观看一公开| 久久国产主播| 亚洲四色影视在线观看| 精品粉嫩aⅴ一区二区三区四区| 欧美精品大片| 另类天堂视频在线观看| 亚洲欧美日韩久久精品| 亚洲人成在线免费观看| 快she精品国产999| 午夜视频在线观看一区二区| 亚洲黄网站在线观看| 国产深夜精品| 国产精品护士白丝一区av| 欧美va天堂va视频va在线| 亚洲欧洲av一区二区三区久久| 日韩亚洲精品在线| 91久久精品国产91久久性色| 欧美va亚洲va日韩∨a综合色| 久久国产视频网站| 羞羞漫画18久久大片|