十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
不知道大家之前對(duì)類似Go語言實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)教程的文章有無了解,今天我在這里給大家再簡(jiǎn)單的講講。感興趣的話就一起來看看正文部分吧,相信看完Go語言實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)教程你一定會(huì)有所收獲的。

目前創(chuàng)新互聯(lián)公司已為1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、白云鄂網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
Go語言官方?jīng)]有實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng),常用的開源MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)實(shí)現(xiàn)如下:
(1)Go MySQL Driver
Go MySQL Driver支持database/sql接口,全部采用Go語言實(shí)現(xiàn)。
官方網(wǎng)站:
https://github.com/go-sql-driver/mysql/
(2)MyMySQL
MyMySQL支持database/sql接口,也支持自定義的接口,全部采用Go語言實(shí)現(xiàn)。
官方網(wǎng)站:
https://github.com/ziutek/mymysql
(3)GoMySQL
GoMySQL不支持database/sql接口,采用自定義接口,全部采用Go語言實(shí)現(xiàn)。
官方網(wǎng)站:
https://github.com/Philio/GoMySQL
Go-MySQL-Driver優(yōu)點(diǎn):
(1)維護(hù)比較好。
(2)完全支持database/sql接口。
(3)支持keepalive,保持長(zhǎng)連接。
Go-MySQL-Driver安裝如下:
go get github.com/go-sql-driver/mysql
導(dǎo)入包:
import "database/sql" import _ "github.com/go-sql-driver/mysql"
登錄MySQL數(shù)據(jù)庫(kù),創(chuàng)建數(shù)據(jù)庫(kù)
create database student default character set utf8;
func Open(driverName, dataSourceName string) (*DB, error)
driverName參數(shù)為數(shù)據(jù)庫(kù)驅(qū)動(dòng)名稱。
dataSourceName是連接參數(shù),參數(shù)格式如下:
user:password@tcp(host:port)/dbname?charset=utf8
func (db *DB) Prepare(query string) (*Stmt, error)
Prepare為后續(xù)查詢或執(zhí)行操作創(chuàng)建一個(gè)準(zhǔn)備SQL
func (s *Stmt) Exec(args ...interface{}) (Result, error)
使用給定參數(shù)執(zhí)行準(zhǔn)備的SQL語句
func (s *Stmt) Query(args ...interface{}) (*Rows, error)
使用給定參數(shù)執(zhí)行準(zhǔn)備的SQL查詢語句
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
執(zhí)行SQL操作,query為SQL語句,可以接收可變參數(shù),用于填充SQL語句的某些字段值。
func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
執(zhí)行SQL查詢操作,可以接收多個(gè)參數(shù)
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func errorHandler(err error) {
if err != nil {
fmt.Println(err.Error())
}
}
var (
CREATE_TABLE = "CREATE TABLE student(" +
"sid INT(10) NOT NULL AUTO_INCREMENT," +
"sname VARCHAR(64) NULL DEFAULT NULL," +
"age INT(10) DEFAULT NULL,PRIMARY KEY (sid))" +
"ENGINE=InnoDB DEFAULT CHARSET=utf8;"
)
// 建立數(shù)據(jù)庫(kù)連接
func setupConnect() *sql.DB {
db, err := sql.Open("mysql", "root:xxxxxx@tcp(118.24.159.133:3306)/student?charset=utf8")
errorHandler(err)
return db
}
// 創(chuàng)建表
func CreateTable(db *sql.DB, sql string) {
_, err := db.Exec(sql)
errorHandler(err)
}
var INSERT_DATA = `INSERT INTO student(sid,sname,age) VALUES(?,?,?);`
// 插入數(shù)據(jù)
func Insert(db *sql.DB) {
db.Exec(INSERT_DATA, 1, "唐僧", 30)
}
var UPDATE_DATA = `UPDATE student SET age=28 WHERE sname="唐僧";`
// 修改數(shù)據(jù)
func Update(db *sql.DB) {
db.Exec(UPDATE_DATA)
}
var DELETE_DATA = `DELETE FROM student WHERE age>=30`
// 刪除記錄
func Delete(db *sql.DB) {
db.Exec(DELETE_DATA)
}
var DELETE_TABLE = `DROP TABLE student;`
// 刪除表
func DeleteTable(db *sql.DB) {
db.Exec(DELETE_TABLE)
}
var QUERY_DATA = `SELECT * FROM student;`
// 查詢數(shù)據(jù)
func Query(db *sql.DB) {
rows, err := db.Query(QUERY_DATA)
if err != nil {
fmt.Println(err)
}
for rows.Next() {
var name string
var id int
var age int
if err := rows.Scan(&id, &name, &age); err != nil {
fmt.Println(err)
}
fmt.Printf("%s is %d\n", name, age)
}
}
func main() {
// 建立數(shù)據(jù)連接
db := setupConnect()
// 創(chuàng)建數(shù)據(jù)庫(kù)表
CreateTable(db, CREATE_TABLE)
// 插入數(shù)據(jù)
Insert(db)
// 查詢數(shù)據(jù)
Query(db)
// 刪除數(shù)據(jù)
Delete(db)
// 插入數(shù)據(jù)
Insert(db)
// 修改數(shù)據(jù)
Update(db)
// 查詢數(shù)據(jù)
Query(db)
// 刪除表
DeleteTable(db)
// 關(guān)閉數(shù)據(jù)庫(kù)連接
db.Close()
}func (db *DB) Begin() (*Tx, error)
開啟事務(wù),從連接池中取出一個(gè)*TX類型連接。使用TX類型連接可以進(jìn)行回滾事務(wù)和提交事務(wù)。
func (tx *Tx) Commit() error
提交事務(wù)
func (tx *Tx) Rollback() error
回滾
func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)
執(zhí)行SQL操作
func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error)
執(zhí)行SQL查詢操作
// 支持事務(wù)回滾機(jī)制的批量數(shù)據(jù)插入
func MultiInsert(db *sql.DB) {
// 批量數(shù)據(jù)插入
tx, err := db.Begin()
if err != nil {
fmt.Println(err)
}
values := [][]interface{}{{2, "孫悟空", 500}, {3, "豬八戒", 200}, {4, "沙悟凈", 100}}
stmt, err := tx.Prepare("INSERT INTO student(sid,sname,age) VALUES(?,?,?);")
for _, val := range values {
_, err := stmt.Exec(val...)
if err != nil {
fmt.Printf("INSERT failed:%v", err)
tx.Rollback()
}
}
tx.Commit()
}func sql.Open(driverName, dataSourceName string) (*DB, error)
sql.Open返回一個(gè)DB對(duì)象,DB對(duì)象對(duì)于多個(gè)goroutines并發(fā)使用是安全的,DB對(duì)象內(nèi)部封裝了連接池。Open函數(shù)并沒有創(chuàng)建連接,只是驗(yàn)證參數(shù)是否合法,然后開啟一個(gè)單獨(dú)goroutine去監(jiān)聽是否需要建立新的連接,當(dāng)有請(qǐng)求建立新連接時(shí)就創(chuàng)建新連接。
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
執(zhí)行不返回行(row)的查詢,比如INSERT,UPDATE,DELETE
DB交給內(nèi)部的exec方法負(fù)責(zé)查詢。exec會(huì)首先調(diào)用DB內(nèi)部的conn方法從連接池里面獲得一個(gè)連接。然后檢查內(nèi)部的driver.Conn是否實(shí)現(xiàn)了Execer接口,如果實(shí)現(xiàn)了Execer接口,會(huì)調(diào)用Execer接口的Exec方法執(zhí)行查詢;否則調(diào)用Conn接口的Prepare方法負(fù)責(zé)查詢。
func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
用于查詢,DB交給內(nèi)部的query方法負(fù)責(zé)查詢。query首先調(diào)用DB內(nèi)部的conn方法從連接池里面獲得一個(gè)連接,然后調(diào)用內(nèi)部的queryConn方法負(fù)責(zé)查詢。
func (db *DB) Prepare(query string) (*Stmt, error)
返回一個(gè)Stmt。Stmt對(duì)象可以執(zhí)行Exec,Query,QueryRow等操作。DB交給內(nèi)部的prepare方法負(fù)責(zé)查詢。prepare首先調(diào)用DB內(nèi)部的conn方法從連接池里面獲得一個(gè)連接,然后調(diào)用driverConn的prepareLocked方法負(fù)責(zé)查詢。
func (db *DB) Begin() (*Tx, error)
開啟事務(wù),返回Tx對(duì)象。調(diào)用Begin方法后,TX會(huì)與指定的連接綁定,一旦事務(wù)提交或者回滾,事務(wù)綁定的連接就還給DB的連接池。DB交給內(nèi)部的begin方法負(fù)責(zé)處理。begin首先調(diào)用DB內(nèi)部的conn方法從連接池里面獲得一個(gè)連接,然后調(diào)用Conn接口的Begin方法獲得一個(gè)TX。
進(jìn)行MySQL數(shù)據(jù)庫(kù)操作時(shí),如果每次SQL操作都從DB對(duì)象的連接池中獲取連接,則會(huì)在很大程度上損耗效率。因此,必須盡量在一個(gè)連接上執(zhí)行SQL操作。
package main
import (
"database/sql"
"fmt"
"strconv"
"time"
_ "github.com/go-sql-driver/mysql"
)
var db = &sql.DB{}
func init() {
db, _ = sql.Open("mysql", "root:xxxxxx@tcp(118.24.159.133:3306)/student?charset=utf8")
CREATE_TABLE := "CREATE TABLE student(" +
"sid INT(10) NOT NULL AUTO_INCREMENT," +
"sname VARCHAR(64) NULL DEFAULT NULL," +
"age INT(10) DEFAULT NULL,PRIMARY KEY (sid))" +
"ENGINE=InnoDB DEFAULT CHARSET=utf8;"
db.Exec(CREATE_TABLE)
}
func update() {
//方式1 update
start := time.Now()
for i := 1001; i <= 1100; i++ {
db.Exec("UPDATE student set age=? where sid=? ", i, i)
}
end := time.Now()
fmt.Println("db.Exec update total time:", end.Sub(start).Seconds())
//方式2 update
start = time.Now()
for i := 1101; i <= 1200; i++ {
stm, _ := db.Prepare("UPDATE student set age=? where sid=? ")
stm.Exec(i, i)
stm.Close()
}
end = time.Now()
fmt.Println("db.Prepare 釋放連接 update total time:", end.Sub(start).Seconds())
//方式3 update
start = time.Now()
stm, _ := db.Prepare("UPDATE student set age=? where sid=?")
for i := 1201; i <= 1300; i++ {
stm.Exec(i, i)
}
stm.Close()
end = time.Now()
fmt.Println("db.Prepare 不釋放連接 update total time:", end.Sub(start).Seconds())
//方式4 update
start = time.Now()
tx, _ := db.Begin()
for i := 1301; i <= 1400; i++ {
tx.Exec("UPDATE student set age=? where sid=?", i, i)
}
tx.Commit()
end = time.Now()
fmt.Println("tx.Exec 不釋放連接 update total time:", end.Sub(start).Seconds())
//方式5 update
start = time.Now()
for i := 1401; i <= 1500; i++ {
tx, _ := db.Begin()
tx.Exec("UPDATE student set age=? where sid=?", i, i)
tx.Commit()
}
end = time.Now()
fmt.Println("tx.Exec 釋放連接 update total time:", end.Sub(start).Seconds())
}
func delete() {
//方式1 delete
start := time.Now()
for i := 1001; i <= 1100; i++ {
db.Exec("DELETE FROM student WHERE sid=?", i)
}
end := time.Now()
fmt.Println("db.Exec delete total time:", end.Sub(start).Seconds())
//方式2 delete
start = time.Now()
for i := 1101; i <= 1200; i++ {
stm, _ := db.Prepare("DELETE FROM student WHERE sid=?")
stm.Exec(i)
stm.Close()
}
end = time.Now()
fmt.Println("db.Prepare 釋放連接 delete total time:", end.Sub(start).Seconds())
//方式3 delete
start = time.Now()
stm, _ := db.Prepare("DELETE FROM student WHERE sid=?")
for i := 1201; i <= 1300; i++ {
stm.Exec(i)
}
stm.Close()
end = time.Now()
fmt.Println("db.Prepare 不釋放連接 delete total time:", end.Sub(start).Seconds())
//方式4 delete
start = time.Now()
tx, _ := db.Begin()
for i := 1301; i <= 1400; i++ {
tx.Exec("DELETE FROM student WHERE sid=?", i)
}
tx.Commit()
end = time.Now()
fmt.Println("tx.Exec 不釋放連接 delete total time:", end.Sub(start).Seconds())
//方式5 delete
start = time.Now()
for i := 1401; i <= 1500; i++ {
tx, _ := db.Begin()
tx.Exec("DELETE FROM student WHERE sid=?", i)
tx.Commit()
}
end = time.Now()
fmt.Println("tx.Exec 釋放連接 delete total time:", end.Sub(start).Seconds())
}
func query() {
//方式1 query
start := time.Now()
rows, _ := db.Query("SELECT sid,sname FROM student")
defer rows.Close()
for rows.Next() {
var name string
var id int
if err := rows.Scan(&id, &name); err != nil {
fmt.Println(err)
}
}
end := time.Now()
fmt.Println("db.Query query total time:", end.Sub(start).Seconds())
//方式2 query
start = time.Now()
stm, _ := db.Prepare("SELECT sid,sname FROM student")
defer stm.Close()
rows, _ = stm.Query()
defer rows.Close()
for rows.Next() {
var name string
var id int
if err := rows.Scan(&id, &name); err != nil {
fmt.Println(err)
}
}
end = time.Now()
fmt.Println("db.Prepare query total time:", end.Sub(start).Seconds())
//方式3 query
start = time.Now()
tx, _ := db.Begin()
defer tx.Commit()
rows, _ = tx.Query("SELECT sid,sname FROM student")
defer rows.Close()
for rows.Next() {
var name string
var id int
if err := rows.Scan(&id, &name); err != nil {
fmt.Println(err)
}
}
end = time.Now()
fmt.Println("tx.Query query total time:", end.Sub(start).Seconds())
}
func insert() {
//方式1 insert
start := time.Now()
for i := 1001; i <= 1100; i++ {
//每次循環(huán)內(nèi)部都會(huì)去連接池獲取一個(gè)新的連接,效率低下
db.Exec("INSERT INTO student(sid,sname,age) values(?,?,?)", i, "student"+strconv.Itoa(i), i-1000)
}
end := time.Now()
fmt.Println("db.Exec insert total time:", end.Sub(start).Seconds())
//方式2 insert
start = time.Now()
for i := 1101; i <= 1200; i++ {
//Prepare函數(shù)每次循環(huán)內(nèi)部都會(huì)去連接池獲取一個(gè)新的連接,效率低下
stm, _ := db.Prepare("INSERT INTO student(sid,sname,age) values(?,?,?)")
stm.Exec(i, "student"+strconv.Itoa(i), i-1000)
stm.Close()
}
end = time.Now()
fmt.Println("db.Prepare 釋放連接 insert total time:", end.Sub(start).Seconds())
//方式3 insert
start = time.Now()
stm, _ := db.Prepare("INSERT INTO student(sid,sname,age) values(?,?,?)")
for i := 1201; i <= 1300; i++ {
//Exec內(nèi)部并沒有去獲取連接,為什么效率還是低呢?
stm.Exec(i, "user"+strconv.Itoa(i), i-1000)
}
stm.Close()
end = time.Now()
fmt.Println("db.Prepare 不釋放連接 insert total time:", end.Sub(start).Seconds())
//方式4 insert
start = time.Now()
//Begin函數(shù)內(nèi)部會(huì)去獲取連接
tx, _ := db.Begin()
for i := 1301; i <= 1400; i++ {
//每次循環(huán)用的都是tx內(nèi)部的連接,沒有新建連接,效率高
tx.Exec("INSERT INTO student(sid,sname,age) values(?,?,?)", i, "user"+strconv.Itoa(i), i-1000)
}
//最后釋放tx內(nèi)部的連接
tx.Commit()
end = time.Now()
fmt.Println("tx.Exec 不釋放連接 insert total time:", end.Sub(start).Seconds())
//方式5 insert
start = time.Now()
for i := 1401; i <= 1500; i++ {
//Begin函數(shù)每次循環(huán)內(nèi)部都會(huì)去連接池獲取一個(gè)新的連接,效率低下
tx, _ := db.Begin()
tx.Exec("INSERT INTO student(sid,sname,age) values(?,?,?)", i, "user"+strconv.Itoa(i), i-1000)
//Commit執(zhí)行后釋放連接
tx.Commit()
}
end = time.Now()
fmt.Println("tx.Exec 釋放連接 insert total time:", end.Sub(start).Seconds())
}
func main() {
insert()
query()
update()
query()
delete()
}
// output:
// db.Exec insert total time: 2.069104068
// db.Prepare 釋放連接 insert total time: 1.869348813
// db.Prepare 不釋放連接 insert total time: 1.447833105
// tx.Exec 不釋放連接 insert total time: 1.098540307
// tx.Exec 釋放連接 insert total time: 3.465670469
// db.Query query total time: 0.005803479
// db.Prepare query total time: 0.010966584
// tx.Query query total time: 0.011800843
// db.Exec update total time: 2.117122871
// db.Prepare 釋放連接 update total time: 2.132430998
// db.Prepare 不釋放連接 update total time: 1.523685366
// tx.Exec 不釋放連接 update total time: 1.346163272
// tx.Exec 釋放連接 update total time: 3.129312377
// db.Query query total time: 0.00848425
// db.Prepare query total time: 0.013472261
// tx.Query query total time: 0.012418198
// db.Exec delete total time: 2.100008271
// db.Prepare 釋放連接 delete total time: 1.9821439490000001
// db.Prepare 不釋放連接 delete total time: 1.429259466
// tx.Exec 不釋放連接 delete total time: 1.103143464
// tx.Exec 釋放連接 delete total time: 2.863670582從示例結(jié)果看,執(zhí)行SQL操作時(shí)如果不釋放連接,則效率比釋放連接要高。
看完Go語言實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)教程這篇文章,大家覺得怎么樣?如果想要了解更多相關(guān),可以繼續(xù)關(guān)注我們的行業(yè)資訊板塊。