go操作數(shù)據(jù)庫

對于許多Web應(yīng)用程序而言,數(shù)據(jù)庫都是其核心所在,數(shù)據(jù)庫幾乎可以用來存儲你想查詢和修改的任何信息。

但是Go本身沒有內(nèi)置任何的驅(qū)動來操作數(shù)據(jù)庫,但是 Go 內(nèi)置 database/sql,里面定義了一些接口,用于可以根據(jù)接口開發(fā)相應(yīng)數(shù)據(jù)庫的驅(qū)動。比如:MySQL、PostgreSQL是不同的數(shù)據(jù)庫,但是我們都可以使用 database/sql 進行操作。常見的數(shù)據(jù)庫驅(qū)動如下:

Mysql: https://github.com/go-sql-driver/mysql
MyMysql: https://github.com/ziutek/mymysql
Postgres: https://github.com/lib/pq
Tidb: https://github.com/pingcap/tidb
SQLite: https://github.com/mattn/go-sqlite3
MsSql: https://github.com/denisenkom/go-mssqldb
Oracle: https://github.com/mattn/go-oci8
這里我們就使用PostgreSQL進行演示。
連接數(shù)據(jù)庫
要想使用Go操作PostgreSQL,那么首先要和數(shù)據(jù)庫之間建立連接,得到DB對象。

import (
    "database/sql"
    _ "github.com/lib/pq"
)

database/sql 是 Go 的標(biāo)準(zhǔn)庫之一,它提供了一系列接口方法,用于訪問關(guān)系數(shù)據(jù)庫。它并不會提供數(shù)據(jù)庫特有的方法,那些特有的方法會交給具體的數(shù)據(jù)庫驅(qū)動去實現(xiàn)。

我們正在加載的驅(qū)動是匿名的,導(dǎo)入之后該驅(qū)動會自行初始化并注冊到 Go 的 database/sql 上下文中,因此我們就可以 database/sql 包提供的方法去訪問數(shù)據(jù)庫了.
下面是建立連接,建立連接的話使用 sql.Open 函數(shù):

func Open(driverName, dataSourceName string) (*DB, error) {
    /*
    driverName: 這個名字就是數(shù)據(jù)庫驅(qū)動注冊到 database/sql 時所使用的名字
               如果是MySQL數(shù)據(jù)庫的話, 那么就是"mysql"; 如果是PostgreSQL數(shù)據(jù)庫的話, 那么就是"postgres";
    dataSourceName: 數(shù)據(jù)庫的連接信息, 這個連接包括了數(shù)據(jù)庫的用戶名、密碼、數(shù)據(jù)庫主機以及連接的數(shù)據(jù)庫名等信息
                   用戶名:密碼@協(xié)議(地址:端口)/數(shù)據(jù)庫?參數(shù)=參數(shù)值
                   
    db, err := sql.Open("postgres", "postgres:zgghyys123@tcp(localhost:5432)/postgres")
    */
}

代碼演示一下:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

func main() {
    // 這里的open函數(shù)只是驗證參數(shù)是否合法, 不會創(chuàng)建和數(shù)據(jù)庫的連接; 得到的僅僅是一個sql.DB對象, 當(dāng)進行數(shù)據(jù)庫查詢的時候才會建立網(wǎng)絡(luò)連接
    // sql.DB 表示操作數(shù)據(jù)庫的抽象接口, 但不是所謂的數(shù)據(jù)庫連接對象, 它只有在需要使用時才會創(chuàng)建連接
    // 注意: dataSourceName結(jié)尾的 sslmode=disable, 如果沒有的話會報錯: pq: SSL is not enabled on the server
    db, err := sql.Open("postgres", "postgres://postgres:zgghyys123@127.0.0.1:5432/postgres?sslmode=disable")
    if err != nil {
        panic(err)
    }
    // 記得關(guān)閉連接, 這里使用defer, 由于該函數(shù)返回一個error, 所以我們放在匿名函數(shù)中
    defer func() {_ = db.Close()}()

    // 如果要立刻檢測數(shù)據(jù)庫源是否能連接到指定的數(shù)據(jù)庫, 需要調(diào)用返回值的Ping方法
    fmt.Println(db.Ping()) // <nil>
    // 打印nil證明沒有錯誤
}

現(xiàn)在來看看go是如何操作mysql的

  1. 安裝驅(qū)動
go get github.com/go-sql-driver/mysql
  1. 導(dǎo)入需要的庫
import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)
  1. 連接數(shù)據(jù)庫
func main() {
    //"用戶名:密碼@[連接方式](主機名:端口號)/數(shù)據(jù)庫名"
    db, _ := sql.Open("mysql", "root:123456@(localhost)/world") // 設(shè)置連接數(shù)據(jù)庫的參數(shù)
    defer db.Close()                                            //關(guān)閉數(shù)據(jù)庫
    err := db.Ping()                                            //連接數(shù)據(jù)庫
    if err != nil {
        fmt.Println("數(shù)據(jù)庫連接失敗")                             //連接失敗
        return
    } else {
        fmt.Println("數(shù)據(jù)庫連接成功")                             //連接成功
    }

  1. 查詢表
rows, _ := db.Query("select * from city") //獲取city表所有數(shù)據(jù)
    var ID, Population int
    var Name, CountryCode, District string
    for rows.Next() { //循環(huán)顯示所有的數(shù)據(jù)
        rows.Scan(&ID, &Name, &CountryCode, &District, &Population)
        fmt.Println(ID, "--", Name, "--", CountryCode, "--", District, "--", Population)
    }
  1. 全部代碼:
package main

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

func main() {
    //"用戶名:密碼@[連接方式](主機名:端口號)/數(shù)據(jù)庫名"
    db, _ := sql.Open("mysql", "root:123456@(localhost)/world") // 設(shè)置連接數(shù)據(jù)庫的參數(shù)
    defer db.Close()                                            //關(guān)閉數(shù)據(jù)庫
    err := db.Ping()                                            //連接數(shù)據(jù)庫
    if err != nil {
        fmt.Println("數(shù)據(jù)庫連接失敗")
        return
    } else {
        fmt.Println("數(shù)據(jù)庫連接成功")
    }

    //多行查詢
    rows, _ := db.Query("select * from city") //獲取所有數(shù)據(jù)
    var ID, Population int
    var Name, CountryCode, District string
    for rows.Next() { //循環(huán)顯示所有的數(shù)據(jù)
        rows.Scan(&ID, &Name, &CountryCode, &District, &Population)
        fmt.Println(ID, "--", Name, "--", CountryCode, "--", District, "--", Population)
    }
}
  1. 拓展
//操作一:執(zhí)行數(shù)據(jù)操作語句

    sql:="insert into stu values (2,'berry')"
    result,_:=db.Exec(sql)      //執(zhí)行SQL語句
    n,_:=result.RowsAffected(); //獲取受影響的記錄數(shù)
    fmt.Println("受影響的記錄數(shù)是",n)

//操作二:執(zhí)行預(yù)處理

    stu:=[2][2] string{{"3","ketty"},{"4","rose"}}
    stmt,_:=db.Prepare("insert into stu values (?,?)")      //獲取預(yù)處理語句對象
    for _,s:=range stu{
        stmt.Exec(s[0],s[1])            //調(diào)用預(yù)處理語句
    }

//操作三:單行查詢

    var id,name string
    rows:=db.QueryRow("select * from stu where id=4")   //獲取一行數(shù)據(jù)
    rows.Scan(&id,&name)        //將rows中的數(shù)據(jù)存到id,name中
    fmt.Println(id,"--",name)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容