【Go】用 Go 访问 MySQL

【Go】用 Go 访问 MySQL,第1张

概述用Go访问MySQLGo语言的database/sql包提供了连接SQL数据库或类SQL数据库的泛用接口,但并不提供具体的数据库驱动程序,在使用它时,必须注入至少一个数据库驱动程序。实现基本的CRUD1.创建数据库和数据库表通过mysql-uroot-p命令进入数据库cmd,然后创建一个 用 Go 访问 MysqL

Go 语言的 database/sql 包提供了连接 sql 数据库或类 sql 数据库的泛用接口,但并不提供具体的数据库驱动程序,在使用它时,必须注入至少一个数据库驱动程序。

实现基本的 CRUD1. 创建数据库和数据库表

通过 MysqL -u root -p 命令进入数据库cmd,然后创建一个 go_MysqL 数据库:

CREATE DATABASE go_MysqL;

进入该数据库: USE go_MysqL;

创建 user 表:

CREATE table `user` {	`uID` BIGINT(20) NOT NulL auto_INCREMENT,	`name` VARCHAR(20) DEFAulT '',	`phone` VARCHAR(20) DEFAulT '',	PRIMARY KEY(`uID`)}ENGINE=InnoDB auto_INCREMENT=1 DEFAulT CHARSET=utf8mb4;
2. 下载 MysqL 的驱动程序
$ go get -u github.com/go-sql-driver/MysqL
3. 使用 MysqL 驱动程序

直接导入依赖包就可以了:

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

在以上语句中,github.com/go-sql-driver/MysqL 就是依赖包。因为没有直接使用该包中的对象,所以在导入包前面被架上了下划线。

database/sql 包中提供了 open() 函数用来连接数据库,其定义如下:

func Open(drivername, dataSourcename string) (*DB, error)

连接示例:

package mainimport (	"database/sql"	_ "github.com/go-sql-driver/MysqL"	"log")func main() {	db, err := sql.Open("MysqL",		"<user>:<password>@tcp(127.0.0.1:3306)/hello")	if err != nil {		log.Fatal(err)	}	defer db.Close()}
4. 初始化连接

在用 open() 函数建立连接后,如果要检查数据源的名称是否合法,则可以调用 Ping 方法。 返回的 DB 对象可以安全地被多个 goroutine 同时使用,并且它会维护自身的闲置连接池。这样 Open 函数只需调用一次,因为一般启动后很少关闭 DB 对象。用 Open 函数初始化连接的示例代码如下:

package mainimport (	"database/sql"	"fmt"	_ "github.com/go-sql-driver/MysqL")var db *sql.DB// 定义一个初始化数据库的函数func initDB() (err error) {	//连接数据库	db, err = sql.Open("MysqL", "root:a123456@tcp(127.0.0.1:3306)/go_MysqL")	if err != nil {		return err	}	// 尝试与数据库建立连接(校验dsn是否正确)	err = db.Ping()	if err != nil {		return err	}	return nil}func main() {	err := initDB() // 调用输出化数据库的函数	if err != nil {		fmt.Printf("init db Failed,err:%v\n", err)		return	}}

其中,sql.DB是一个数据库的 *** 作句柄,代表一个具有零到多个底层连接的连接池。它可以安全地被多个 goroutine同时使用。 database/sql包会自动创建和释放连接,也会维护一个闲置连接的连接池。

5. sql 查询(1)查

首先定义一个结构体用来存储数据库返回的数据:

type User struct {	UID   int	name  string	Phone string}

有两种查询方式:

queryRow() 进行单行查询query() 进行多行查询

单行查询示例:

// 单行测试func queryRow() {    var u User	// 非常重要:确保queryRow之后调用Scan方法,否则持有的数据库链接不会被释放	err := db.queryRow("select uID,name,phone from `user` where uID=?", 1).Scan(&u.UID, &u.name, &u.Phone)	if err != nil {		fmt.Printf("scan Failed, err:%v\n", err)		return	}	fmt.Printf("uID:%d name:%s phone:%s\n", u.UID, u.name, u.Phone)}

多行查询示例:

// 查询多条数据示例func querymultirow() {    var u User	rows, err := db.query("select uID,name,phone from `user` where uID > ?", 0)	if err != nil {		fmt.Printf("query Failed, err:%v\n", err)		return	}	// 关闭rows释放持有的数据库链接	defer rows.Close()	// 循环读取结果集中的数据	for rows.Next() {		err := rows.Scan(&u.UID, &u.name, &u.Phone)		if err != nil {			fmt.Printf("scan Failed, err:%v\n", err)			return		}		fmt.Printf("uID:%d name:%s phone:%s\n", u.UID, u.name, u.Phone)	}}
(2)插、改、删

使用 Exec() 方法

MysqL 预处理什么是预处理

要了解预处理,需要首先了解普通@R_404_5967@的执行过程:

客户端对@R_404_5967@进行占位符替换,得到完整的@R_404_5967@;客户端发送完整的@R_404_5967@到 MysqL 服务器端;MysqL服务器端执行完整的@R_404_5967@,并将结果返给客户端。预处理的执行过程把@R_404_5967@分成两部分——命令部分与数据部分;把命令部分发送给 MysqL 服务器端, MysqL 服务器端进行sql预处理;把数据部分发送给 MysqL 服务器端, MysqL 服务器端对@R_404_5967@进行占位符替换;MysqL 服务器端执行完整的 sql 语句,并将结果返回给客户端为什么要预处理?

预处理用于优化 MysqL 服务器重复执行 sql 语句的问题,可以提升服务器性能。提前让服务器编译,一次编译多次执行,可以节省后续编译的成本,避免sql注入问题。

Go 语言中 MysqL 的预处理

在Go语言中, Prepare()方法会将@R_404_5967@发送给 MysqL服务器端,返回一个准备好的状 态用于之后的查询和命令。返回值可以同时执行多个查询和命令。 Prepare() 方法的定义如下:

func (db *DB) Prepare(query string) (*Stmt, error)

预处理的示例代码:

// 预处理查询示例func preparequery() {	stmt, err := db.Prepare("select uID,name,phone from `user` where uID > ?")	if err != nil {		fmt.Printf("prepare Failed, err:%v\n", err)		return	}	defer stmt.Close()	rows, err := stmt.query(0)	if err != nil {		fmt.Printf("query Failed, err:%v\n", err)		return	}	defer rows.Close()	// 循环读取结果集中的数据    var user User	for rows.Next() {		err := rows.Scan(&u.UID, &u.name, &u.Phone)		if err != nil {			fmt.Printf("scan Failed, err:%v\n", err)			return		}		fmt.Printf("uID:%d name:%s phone:%s\n", u.UID, u.name, u.Phone)	}}
用 Go 实现 MysqL 事务1. 什么是事务

事务是一个最小的不可再分的工作单元。通常一个事务对应一个完整的业务(例如银行账户 转账业务,该业务就是一个最小的工作单元),同时这个完整的业务需要执行多次 DML ( INSERT、 UPDATE、 DELETE等)语句,共同联合完成。 例如,A转账给B,就需要执行两次 UPDATE *** 作。在 MysqL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。 事务处理用来维护数据库的完整性,保证成批的@R_404_5967@要么全部执行,要么全部不执行。

2. 事务的 ACID 属性

通常事务必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性 ( Consistency)、隔离性( Isolation,又称独立性)、持久性( Durability)事务的 ACID 属性。

3. 事务的相关方法

Go 语言使用以下三个方法来实现 MysqL 中的事务 *** 作:

Begin() 方法用于开始事务:

func (db *DB) Begin() (*Tx, error)

Commit() 方法用于提交事务:

func (tx *Tx) Commit() error

Rollback() 方法用于回滚事务:

func (tx *Tx) Rollback() error

以下代码演示了一个简单的事务 *** 作,该事务 *** 作能够确保两次更新 *** 作要么同时成功,要么同时失败,不会有中间状态:

func transaction() {	tx, err := db.Begin() // 开启事务	if err != nil {		if tx != nil {			tx.Rollback() // 回滚		}		fmt.Printf("begin trans Failed, err:%v\n", err)		return	}	_, err = tx.Exec("update user set username='james' where uID=?", 1)	if err != nil {		tx.Rollback() // 回滚		fmt.Printf("exec sql1 Failed, err:%v\n", err)		return	}	_, err = tx.Exec("update user set username='james' where uID=?", 3)	if err != nil {		tx.Rollback() // 回滚		fmt.Printf("exec sql2 Failed, err:%v\n", err)		return	}	err = tx.Commit() // 提交事务	if err != nil {		tx.Rollback() // 回滚		fmt.Printf("commit Failed, err:%v\n", err)		return	}	fmt.Println("exec transaction success!")}
sql 注入与防御

在编写 sql 脚本时,尽量不要自己拼接 sql 语句。

针对sql注入问题,常见的防御措施有:

禁止将变量直接写入@R_404_5967@。对用户进行分级管理,严格控制用户的权限。对用户输入进行检查,确保数据输入的安全性。在具体检查输入或提交的变量时,对单引 号、双引号、冒号等字符进行转换或者过滤。对数据库信息进行加密。 总结

以上是内存溢出为你收集整理的【Go】用 Go 访问 MySQL全部内容,希望文章能够帮你解决【Go】用 Go 访问 MySQL所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1211862.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存