Day.16 应用中学习- 资料库操作 ( golang / sql )

身处後端开发一定会接触到写code去操作资料库的需求,所以今天主题来介绍一点实务应用,透过Golang操作mysql资料库,程序如何控制事务的提交与回滚&资料异动操作~

连线资料库设置

package main

import (
	"database/sql"
	"fmt"

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

func main() {

	//Init connect object.  content-> account:password@tcp(host_ip:port)/db_name
	dbu, err := sql.Open("mysql", "root:1234@tcp(127.0.0.1:3306)/user?charset=utf8&parseTime=True")
	if err != nil {
		fmt.Println("open mysql error", err)
		return
	}

	//close conn.
	defer dbu.Close()

	//Create mysql connect.
	err = dbu.Ping()
	if err != nil {
		fmt.Println("create mysql connect  error", err)
		return
	}

	/*
		>以下连接池设定
		    注意点:
			(1.)mysql连线预设保存时间为8小时,闲置超过8小时会被mysql断开变失效连线。
				查询: show variables like '%wait_timeout%';

				注意: 使用到被mysql断开的连线会产生ERROR -> packets.go:36: unexpected EOF

			(2.)mysql最大连线数。
				查询: show variables like '%max_connections%';

	*/

	//设置最大并发连线数,超过连线数需等待,直到其中连接被释放并变为空闲。
	dbu.SetMaxOpenConns(100)
	//设置最大的空闲连接数,适当的设定空闲连接数(会占用内存)将提高性能,减少从头建立新连接的可能。
	dbu.SetMaxIdleConns(10)
	//设置连线的生命周期,过期後无法重用。
	dbu.SetConnMaxLifetime(30)
}

(1.)建立资料库
CREATE DATABASE user;

(2.)建立资料表
CREATE TABLE `user_lists` (
  `user_id` bigint(20) NOT NULL COMMENT '使用者ID',
  `account` varchar(50) NOT NULL COMMENT '帐号',
  `level` tinyint(5) NOT NULL COMMENT '层级',
  `last_login_time` int(11) NOT NULL COMMENT '最後登入时间',
  `create_time` int(11) NOT NULL COMMENT '建立时间',
  PRIMARY KEY (`user_id`)
);

进入正题~透过mysql driver对user_list这张表进行资料存取操作。

  • Exec() -> 执行写入异动SQL操作。
//异动数据 ( 新增/删除/更新 )
func ExecSQL(dbu *sql.DB) error {

	//INSERT INTO user_list(user_id,account,level,last_login_time,create_time) values(8723131, "siangx", 1, 1630385990, 1530385990);

	sql := "INSERT INTO user_list(user_id,account,level,last_login_time,create_time) values(?,?,?,?,?)"

	res, err := dbu.Exec(sql, 8723131, "siangx", 1, 1630385990, 1530385990)
	if err != nil {
		fmt.Println("insert user table error", err)
		return err
	}
	//返回执行影响笔数
	count, err := res.RowsAffected()
	if err != nil {
		fmt.Println("get RowsAffected error", err)
		return err
	}
	fmt.Printf("[OK] %d row affected ", count)

	return nil
}
  • Query() -> 执行数据库查询操作(多笔) & QueryRow() -> 执行数据库查询操作(单笔)。
//查询数据
func QuerySQL(dbu *sql.DB) {

	//先定义欲搜寻栏位的资料结构
	type User struct {
		UserID  int64
		Account string
		Level   int
	}

	/*
		var userLists User
		//单笔查询
		if err := dbu.QueryRow("SELECT user_id,account,level FROM user_list WHERE user_id = ?", 8723131).
			Scan(&userLists.UserID, &userLists.Account, &userLists.Level); err != nil {
			fmt.Println("query user table error", err)
		}
		log.Println(userLists)
	*/

	//查询内容可能包含一笔(含)以上使用Query

	//定义好要回传的栏位结构
	var userList []User

	//send query sql to mysql
	rows, err := dbu.Query("SELECT user_id,account,level FROM user_list WHERE user_id = ?", 8723131)
	if err != nil {
		fmt.Println("query user table error", err)
	}

	// close sql.Rows -> 重要: 记得要有这个动作去手动释放连线。
	defer rows.Close()

	//read sql response rows -> 遍历读取出来的row资讯存入定义好的User结构
	for rows.Next() {
		user := User{}
		err := rows.Scan(&user.UserID, &user.Account, &user.Level)
		if err != nil {
			fmt.Println("get user row data error", err)
		}
		userList = append(userList, user)
	}

	fmt.Printf("query response: %+v:", userList)
}

最後是我们的Transaction~
还记得前面我们提到用MYSQL CLI手动执行一个事务流程吧,现在换用程序来控制。

复习一下:

  1. 进入交易模式- begin
  2. 本次交易要执行的SQL内容(update/insert....)
  3. 结束交易模式- commit
  • 当交易过程中有发生错误时- rollback (表示取消交易,还原到未交易时的状态)

明天写一个简单的应用流程来说明事务提交流程~


<<:  Day12回圈(Ⅱ)

>>:  D10 - 「数位×IN×OUT」

【Day20】:Servo控制-By PWM输出

Servo 对於简单的角度控制,大家第一个想到的就是伺服马达了吧,大小也适中,非常适合用在机器人上。...

今天就改变你的人生!不要寄望将来,立即行动,停止拖延。

今天就改变你的人生!不要寄望将来,立即行动,停止拖延。 Change your life today...

[DAY-17] 热情从何处来

2021 最後一季拉!!! 倒数 3 个月 当兵有破百 每年的此时此刻也进入破百的阶段拉!!! 前...

【情蒐阶段】确认自己的目标、熟悉职缺市场

今天早上泡了杯 wushwush,打开我的 Leetcode, 啊又是一个觉得智力不足的 momen...

Day 01 阿修补坑中

第一天先来聊聊我的背景以及为什麽我会想写这个主题 原本我是一名品保工程师,做了3、4年发现这份工作开...