• <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>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            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 楊粼波 閱讀(342) 評論(0)  編輯 收藏 引用

            2021国产精品久久精品| 久久精品国产精品亚洲下载| 国产女人aaa级久久久级| 2022年国产精品久久久久| 午夜精品久久久久久毛片| 久久亚洲熟女cc98cm| 久久99久久99精品免视看动漫| 久久综合一区二区无码| 看全色黄大色大片免费久久久| 久久精品国产第一区二区| 久久本道久久综合伊人| 亚洲国产成人久久一区久久| 色妞色综合久久夜夜| 狠狠色婷婷久久一区二区| 色偷偷88888欧美精品久久久| 97r久久精品国产99国产精| 66精品综合久久久久久久| 久久www免费人成精品香蕉| 久久久久久国产a免费观看黄色大片| 国产精品久久久久蜜芽| 国内精品久久久久久99| 久久综合九色综合久99| 国产99久久久国产精品小说| 性欧美丰满熟妇XXXX性久久久| 久久免费精品一区二区| 一本色道久久综合狠狠躁篇 | 日本精品久久久中文字幕| 日韩一区二区久久久久久| 中文字幕精品久久久久人妻| 99国产精品久久久久久久成人热| 日本免费久久久久久久网站| 欧美亚洲国产精品久久| 久久99热国产这有精品| 99精品久久久久久久婷婷| 伊人色综合久久天天| 亚洲午夜久久久久久久久电影网| 久久久久久久99精品免费观看| 亚洲欧美成人久久综合中文网 | 久久久久久久免费视频| 91精品国产综合久久精品| 久久综合色老色|