Go語言操作MySQL語言基礎(chǔ)知識(shí)
前言
通常情況下,我們程序員和數(shù)據(jù)庫(kù)打交道是最多的。要然我們?cè)趺磿?huì)被稱為碼農(nóng)呢。
存用戶信息需要數(shù)據(jù)庫(kù),存訂單需要數(shù)據(jù)庫(kù),等等等等,現(xiàn)在真是數(shù)據(jù)驅(qū)動(dòng)著發(fā)展。
但是數(shù)據(jù)庫(kù)種類有很多,有Mysql,Oracle,SQL Server。
本篇就示例如何Go操作Mysql。
準(zhǔn)備工作
本次使用的是go mod進(jìn)行包依賴管理,還不會(huì)使用的向上爬梯子,找go mod用法。
使用的庫(kù)是第三方庫(kù)go-sql-driver/mysql。
準(zhǔn)備工作之連接數(shù)據(jù)庫(kù)
代碼
- func main() {
 - var username = "root"
 - var password = "rootroot"
 - var ip = "127.0.0.1"
 - var port = "3306"
 - var data = "go_mysql_demo"
 - var dsn = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", username, password, ip, port, data)
 - //Open只會(huì)驗(yàn)證dsb的格式是否正確,不會(huì)驗(yàn)證是否連接成功,同理,密碼是否正確也不知道
 - db, err := sql.Open("mysql", dsn)
 - if err != nil {
 - panic(err)
 - }
 - //關(guān)閉連接在 err 之后,因?yàn)榭赡苤苯泳痛蜷_不成功,關(guān)閉一個(gè)沒有打開的連接???
 - defer db.Close()
 - // 此時(shí)嘗試連接數(shù)據(jù)庫(kù),會(huì)判斷用戶,密碼,ip地址,端口是否正確
 - err = db.Ping()
 - if err != nil {
 - fmt.Println("連接數(shù)據(jù)庫(kù)失敗,",err)
 - return
 - }
 - //設(shè)置與數(shù)據(jù)庫(kù)建立連接的最大數(shù)目,一般不管
 - db.SetMaxOpenConns(100)
 - //設(shè)置連接池中的最大閑置連接數(shù),一般不管
 - db.SetMaxIdleConns(50)
 - }
 
注意
- sql.Open只會(huì)驗(yàn)證格式是否正確,不會(huì)連接數(shù)據(jù)庫(kù)。
 - db.Close在err之后,是因?yàn)榭赡艽蜷_不成功,關(guān)閉一個(gè)沒有打開的連接。
 - db.Ping會(huì)連接數(shù)據(jù)庫(kù),判斷用戶,密碼,ip地址,端口是否正確。
 
準(zhǔn)備工作之創(chuàng)建表
我們創(chuàng)建一個(gè)簡(jiǎn)單的用戶表。
- CREATE TABLE `userinfo` (
 - `id` int(11) NOT NULL AUTO_INCREMENT,
 - `name` varchar(10) DEFAULT NULL,
 - `phone` char(11) DEFAULT NULL,
 - `address` varchar(64) DEFAULT NULL,
 - PRIMARY KEY (`id`)
 - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
準(zhǔn)備工作之創(chuàng)建結(jié)構(gòu)體
假設(shè)上述工作都完成了啊。
不知道有沒有想過,我們查詢的數(shù)據(jù),存成啥?,字符串?map?切片?,似乎都不是太好。
只有結(jié)構(gòu)體是最清晰的,最好認(rèn)識(shí)的。
結(jié)構(gòu)體
- type Userinfo struct {
 - Id int64 `json:"id"`
 - Name string `json:"name"`
 - Phone string `json:"phone"`
 - Address string `json:"address"`
 - }
 
查詢單條
單條查詢使用QueryRow方法。
代碼
- //查詢單條
 - sqlStr := "SELECT id,`name`,phone,address from userinfo where id = ?;"
 - var user Userinfo
 - /*
 - QueryRow 第二個(gè)參數(shù)可以接收多個(gè)參數(shù),同理,sqlStr可以有多個(gè) ?占位符 進(jìn)行匹配
 - QueryRow 之后必須調(diào)用Scan方法進(jìn)行數(shù)據(jù)綁定,進(jìn)行數(shù)據(jù)庫(kù)鏈接釋放
 - */
 - err = db.QueryRow(sqlStr, 1).Scan(&user.Id, &user.Name, &user.Phone, &user.Address)
 - if err != nil {
 - fmt.Println("查詢失敗", err)
 - return
 - }
 - fmt.Println(user)
 
執(zhí)行結(jié)果

查詢多條
多行查詢使用Query。
代碼
- //查詢多條
 - sqlStr := "SELECT id,`name`,phone,address from userinfo where id >= ?"
 - //參數(shù)同 QueryRow
 - rows, err := db.Query(sqlStr, 1)
 - if err != nil {
 - fmt.Println("查詢失敗:", err)
 - return
 - }
 - // 此處使用rows釋放所有鏈接
 - defer rows.Close()
 - //循環(huán)整理所有數(shù)據(jù)
 - var userList = make([]Userinfo, 0, 10)
 - for rows.Next() {
 - var user Userinfo
 - err = rows.Scan(&user.Id, &user.Name, &user.Phone, &user.Address)
 - if err != nil {
 - fmt.Println("綁定數(shù)據(jù)失敗", err)
 - return
 - }
 - userList = append(userList, user)
 - }
 - fmt.Println(userList)
 
執(zhí)行結(jié)果

插入數(shù)據(jù)
插入數(shù)據(jù)需要用到Exec。
代碼
- //插入數(shù)據(jù)
 - sqlStr := "INSERT into userinfo(name,phone,address) values(?,?,?);"
 - result, err := db.Exec(sqlStr, "吳彥祖", 555, "不知道哪的")
 - if err != nil {
 - fmt.Println("插入失敗", err)
 - return
 - }
 - //受影響的行數(shù)
 - row_affect, err := result.RowsAffected()
 - if err != nil {
 - fmt.Println("受影響行數(shù)獲取失敗:", err)
 - return
 - }
 - fmt.Println("受影響的行數(shù):", row_affect)
 - lastId, err := result.LastInsertId()
 - if err != nil {
 - fmt.Println("新增行id獲取失敗:", err)
 - return
 - }
 - fmt.Println("新增行id:", lastId)
 - fmt.Println("插入成功")
 
執(zhí)行結(jié)果

Mysql

更新數(shù)據(jù)
更新和添加差不多,用的都是Exec。
代碼
- //更新數(shù)據(jù)
 - sqlStr := `UPDATE userinfo set name=? where id=?;`
 - result, err := db.Exec(sqlStr, "吳彥祖666", 3)
 - if err != nil {
 - fmt.Println("更新失敗", err)
 - return
 - }
 - //受影響的行數(shù)
 - row_affect, err := result.RowsAffected()
 - if err != nil {
 - fmt.Println("受影響行數(shù)獲取失敗:", err)
 - return
 - }
 - fmt.Println("受影響的行數(shù):", row_affect)
 - fmt.Println("更新成功")
 
執(zhí)行結(jié)果

Mysql

刪除數(shù)據(jù)
刪除數(shù)據(jù)用的還是Exec。
代碼
- //刪除數(shù)據(jù)
 - sqlStr := "delete from userinfo where id = ?;"
 - result, err := db.Exec(sqlStr, 3)
 - if err != nil {
 - fmt.Println("刪除失敗", err)
 - return
 - }
 - //受影響的行數(shù)
 - row_affect, err := result.RowsAffected()
 - if err != nil {
 - fmt.Println("受影響行數(shù)獲取失敗:", err)
 - return
 - }
 - fmt.Println("受影響的行數(shù):", row_affect)
 - fmt.Println("刪除成功")
 
執(zhí)行結(jié)果

Mysql

事物
事物,這個(gè)用的就比較多了,通常用在關(guān)鍵的場(chǎng)景。
尤其是轉(zhuǎn)賬,張三-10塊,李四+10塊,這個(gè)動(dòng)作動(dòng)作是要在一起完成的。
如果任何一個(gè)失敗了,就要恢復(fù)上一次的狀態(tài)。
我們通常也叫這個(gè)操作叫做原子操作,要成功,都成功,要完蛋,都完蛋。
新建表
- CREATE TABLE `bill` (
 - `id` int(11) NOT NULL AUTO_INCREMENT,
 - `name` varchar(8) NOT NULL,
 - `money` int(11) NOT NULL,
 - PRIMARY KEY (`id`)
 - ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
 
表數(shù)據(jù)
張三和李四都剩余100塊

Go Mysql 關(guān)于事物相關(guān)方法
Go 關(guān)于事物有三個(gè)方法
- Begin()開始事物。
 - Commit()提交事物。
 - Rollback()失敗回滾。
 
模擬轉(zhuǎn)賬:張三-10塊,李四+十塊
代碼
- func main() {
 - //事物
 - //開啟事物
 - tx, err := db.Begin()
 - if err != nil {
 - //釋放事物
 - if tx != nil {
 - tx.Rollback()
 - }
 - fmt.Println("事物開啟失敗")
 - return
 - }
 - 張三減10塊Sql := `UPDATE bill set money=money - 10 where name = ?;`
 - result, err := tx.Exec(張三減10塊Sql, "張三")
 - if err != nil {
 - //有錯(cuò)誤表示更是失敗,回滾原來狀態(tài)
 - tx.Rollback()
 - fmt.Println(err)
 - return
 - }
 - 張三受影響行數(shù), err := result.RowsAffected()
 - if err != nil {
 - tx.Rollback() // 回滾
 - return
 - }
 - 李四加10塊Sql := `UPDATE bill set money=money + 10 where name = ?;`
 - result, err = tx.Exec(李四加10塊Sql, "李四")
 - if err != nil {
 - //有錯(cuò)誤表示更是失敗,回滾原來狀態(tài)
 - tx.Rollback()
 - fmt.Println(err)
 - return
 - }
 - 李四受影響行數(shù), err := result.RowsAffected()
 - if err != nil {
 - tx.Rollback() // 回滾
 - return
 - }
 - //都等于1表示成功,可以提交事務(wù),修改數(shù)據(jù)
 - if 張三受影響行數(shù)==1 && 李四受影響行數(shù)==1{
 - //提交事務(wù)
 - fmt.Println("提交事務(wù)")
 - tx.Commit()
 - }else{
 - //有一個(gè)!=1表示沒有更新成功,可能用戶不存在
 - fmt.Println("失敗了,事物回滾了")
 - tx.Rollback()
 - }
 - fmt.Println("事物執(zhí)行成功")
 - }
 
執(zhí)行結(jié)果

Mysql
一加一減

假如出錯(cuò)了

Mysql
如果使用事物,出錯(cuò)了數(shù)據(jù)還是沒變。

總結(jié)
本次主要講述了Go如何操作Mysql,如何進(jìn)行增刪改查,最后還講了以下什么是事物,如何操作事物。
當(dāng)然,這種是最原始的方法,過程有些繁瑣,了解入門就好,后面還有更方便的方法。

















 
 
 






 
 
 
 