Go語言操作MySQL數據庫


Go語言操作MySQL數據庫

MySQL是一個關系型數據庫管理系統,由瑞典MySQL AB 公司開發,目前屬於 Oracle 旗下產品。MySQL 是最流行的關系型數據庫管理系統之一,在 WEB 應用方面,MySQL是最好的 RDBMS (Relational Database Management System,關系數據庫管理系統) 應用軟件。

Go語言MySQL包
使用第三方開源的mysql庫:

github.com/go-sql-driver/mysql (MySQL驅動)
github.com/jmoiron/sqlx (基於MySQL驅動的封裝)
 
通過如下命令,保存下載第三方庫:
go get github.com/go-sql-driver/mysql
go get github.com/jmoiron/sqlx 

創建數據庫、數據表
在MySQL下創建 oldboy庫:
mysql> CREATE DATABASE IF NOT EXISTS oldboy DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

在oldboy庫中創建student表。
mysql> use oldboy;

mysql> CREATE TABLE IF NOT EXISTS `student`(
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `name` varchar(100) NOT NULL,
    `sex` varchar(40) NOT NULL,
    `age` int(11) DEFAULT NULL,
    `course` varchar(100) NOT NULL,
    PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;


MySQL連接池
數據庫連接使用datebase/sql Open函數進行連接,用戶應該通過db.Ping()函數來檢查數據庫是否實際可用。

package main

import (
    "fmt"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

func main() {
    //DB, err := sqlx.Open("數據庫類型", "用戶名:密碼@tcp(地址:端口)/數據庫名")
    DB, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
    if err != nil {
        fmt.Println("Open mysql failed,", err)
    }
    err = DB.Ping()
    if err != nil {
        fmt.Println("Ping mysql failed,", err)
    } else {
        fmt.Println("MySQL client success")
    }
}


連接池配置
配置連接池有兩個的函數:
設置最大數據庫連接:使用 db.SetMaxOpenConns(n int) 函數設置打開數據庫的最大連接數。包含正在使用的連接和連接池的連接。如果你的函數調用需要申請一個連接,並且連接池已經沒有了連接或者連接數達到了最大連接數。此時的函數調用將會被block,直到有可用的連接才會返回。設置這個值可以避免並發太高導致連接mysql出現too many connections的錯誤。該函數的默認設置是0,表示無限制。
設置最大空閑連接:使用db.SetMaxIdleConns(n int) 函數設置連接池中的保持連接的最大連接數。默認也是0,表示連接池不會保持釋放會連接池中的連接的連接狀態:即當連接釋放回到連接池的時候,連接將會被關閉。這會導致連接再連接池中頻繁的關閉和創建。



插入操作
建議使用結構化操作,不推薦使用直接拼接sql語句的方法。
package main

import (
    "fmt"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

type Student struct {
    Id     int    `db:"id"`
    Name   string `db:"name"`
    Sex    string `db:"sex"`
    Age    int    `db:"age"`
    Course string `db:"course"`
}

var Db *sqlx.DB

func init() {
    database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = database
}

func main() {
    r, err := Db.Exec("insert into student(name, sex, age, course)values(?, ?, ?, ?)", "張三", "", 18, "Golang")
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }
    id, err := r.LastInsertId()
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }

    fmt.Println("insert succ:", id)
}



查詢操作
package main

import (
    "fmt"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

type Student struct {
    Id     int    `db:"id"`
    Name   string `db:"name"`
    Sex    string `db:"sex"`
    Age    int    `db:"age"`
    Course string `db:"course"`
}

var Db *sqlx.DB

func init() {
    database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = database
}

func main() {
    var student []Student
    err := Db.Select(&student, "select id, name, sex, age, course from student where course=?", "Golang")
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }

    fmt.Println("select succ:", student)
}



修改操作
package main

import (
    "fmt"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

type Student struct {
    Id     int    `db:"id"`
    Name   string `db:"name"`
    Sex    string `db:"sex"`
    Age    int    `db:"age"`
    Course string `db:"course"`
}

var Db *sqlx.DB

func init() {
    database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = database
}

func main() {
    res, err := Db.Exec("update student set name=? where course=?", "李四", "Golang")
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }
    row, err := res.RowsAffected()
    if err != nil {
        fmt.Println("rows failed, ", err)
    }
    fmt.Println("update succ:", row)
}



刪除操作
package main

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

type Student struct {
    Id     int    `db:"id"`
    Name   string `db:"name"`
    Sex    string `db:"sex"`
    Age    int    `db:"age"`
    Course string `db:"course"`
}

var Db *sqlx.DB

func init() {
    database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = database
}

func main() {
    res, err := Db.Exec("delete from student where name=?", "李四")
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }

    row, err := res.RowsAffected()
    if err != nil {
        fmt.Println("rows failed, ", err)
    }

    fmt.Println("delete succ: ", row)
}
修改和刪除操作都比較簡單,同插入數據類似,只是使用RowsAffected來獲取影響的數據行數。



MySQL事務
MySQL 事務主要用於處理操作量大,復雜度高的數據。
在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務。
事務處理可以用來維護數據庫的完整性,保證成批的 SQL 語句要么全部執行,要么全部不執行。
事務用來管理 insert,update,delete 語句
一般來說,事務是必須滿足4個條件(ACID):原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨立性)、持久性(Durability)。

Go語言MySQL事務應用包與函數:
1) import ("github.com/jmoiron/sqlx")
2)  conn, err := Db.Begin()    開始事務
3)  conn.Commit()              提交事務
4)  conn.Rollback()            回滾事務


事務應用
package main

import (
    "fmt"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

type Student struct {
    Id     int    `db:"id"`
    Name   string `db:"name"`
    Sex    string `db:"sex"`
    Age    int    `db:"age"`
    Course string `db:"course"`
}

var Db *sqlx.DB

func init() {
    database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = database
}

func main() {
    conn, err := Db.Begin()
    if err != nil {
        fmt.Println("begin failed :", err)
        return
    }

    r, err := Db.Exec("insert into student(name, sex, age, course)values(?, ?, ?, ?)", "王五", "", 18, "Golang")
    if err != nil {
        fmt.Println("exec failed, ", err)
        conn.Rollback()
        return
    }
    id, err := r.LastInsertId()
    if err != nil {
        fmt.Println("exec failed, ", err)
        conn.Rollback()
        return
    }
    fmt.Println("insert succ:", id)

    r, err = Db.Exec("insert into student(name, sex, age, course)values(?, ?, ?, ?)", "趙六", "", 18, "Linux、Python、Java")
    if err != nil {
        fmt.Println("exec failed, ", err)
        conn.Rollback()
        return
    }
    id, err = r.LastInsertId()
    if err != nil {
        fmt.Println("exec failed, ", err)
        conn.Rollback()
        return
    }
    fmt.Println("insert succ:", id)

    conn.Commit()
}

查看MySQL:
mysql> select id,name,sex,age,course from student;
+----+--------+-----+------+-----------------------+
| id | name   | sex | age  | course                |
+----+--------+-----+------+-----------------------+
|  2 | 王五   | 男  |   18 | Golang                |
|  3 | 趙六   | 男  |   18 | Linux、Python、Java   |
+----+--------+-----+------+-----------------------+
2 rows in set (0.00 sec)



Go語言操作mysql除使用 github.com/go-sql-driver/mysql第三方開源的mysql庫外還可以使用github.com/jinzhu/gorm包,GORM是使用Go語言開發的友好的ORM庫。

安裝
go get -u github.com/jinzhu/gorm

通用數據庫接口sql.DB
從*gorm.DB連接獲取通用數據庫接口*sql.DB

// 獲取通用數據庫對象`*sql.DB`以使用其函數
db.DB()

// Ping
db.DB().Ping()

連接池
db.DB().SetMaxIdleConns(10)
db.DB().SetMaxOpenConns(100)

復合主鍵
將多個字段設置為主鍵以啟用復合主鍵

type Product struct {
    ID           string `gorm:"primary_key"`
    LanguageCode string `gorm:"primary_key"`
}


日志
Gorm有內置的日志記錄器支持,默認情況下,它會打印發生的錯誤

// 啟用Logger,顯示詳細日志
db.LogMode(true)

// 禁用日志記錄器,不顯示任何日志
db.LogMode(false)

// 調試單個操作,顯示此操作的詳細日志
db.Debug().Where("name = ?", "jinzhu").First(&User{})

自定義日志
參考GORM的默認記錄器如何自定義
https://github.com/jinzhu/gorm/blob/master/logger.go

db.SetLogger(gorm.Logger{revel.TRACE})
db.SetLogger(log.New(os.Stdout, "\r\n", 0))



架構
Gorm使用可鏈接的API,*gorm.DB是鏈的橋梁,對於每個鏈API,它將創建一個新的關系。
db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")

// 創建新關系
db = db.Where("name = ?", "jinzhu")

// 過濾更多
if SomeCondition {
    db = db.Where("age = ?", 20)
} else {
    db = db.Where("age = ?", 30)
}
if YetAnotherCondition {
    db = db.Where("active = ?", 1)
}
當我們開始執行任何操作時,GORM將基於當前的*gorm.DB創建一個新的*gorm.Scope實例

// 執行查詢操作
db.First(&user)
並且基於當前操作的類型,它將調用注冊的creating,updating,querying,deleting或row_querying回調來運行操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM