Go语言中database/sql的用法介绍
作者:今天捡到一百块钱
Go语言中的database/sql包定义了对数据库的一系列操作,database/sql/driver包定义了应被数据库驱动实现的接口,这些接口会被sql包使用,本文将详细给大家介绍Go的database/sql的使用方法,需要的朋友可以参考下
零、windows系统安装MySQL
- 访问MySQL的官网:MySQL :: Download MySQL Community Server (Archived Versions)
- 下载5.6.47版本的MySQL压缩包
- 在本地解压MySQL压缩包
- 将MySQL解压的位置添加到机器的环境变量中
- 将MySQL设置成系统服务
mysqld --install // 将mysql设置成系统服务 mysqld --remove // 取消MySQL作为系统服务
- 修改MySQL的登录密码
mysqladmin -uroot -p原密码 password 新密码 mysqladmin -uroot -p password 123456 // 刚安装的MySQL默认是没有密码的
一、简介
Go 语言中的 database/sql 包定义了对数据库的一系列操作。database/sql/driver 包定义了应被数据库驱动实现的接口,这些接口会被 sql 包使用。但是 Go 语言没有提供任何官方的数据库驱动,所以我们需要导入第三方的数据库驱动。不过我们连接数据库之后对数据库操作的大部分代码都使用sql 包。 目前go用的比较多的关系型数据库有mysql和sqlite3,以下是第三方的驱动地址。
二、连接数据库
代码实现
package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" // It is important "log" ) func main() { dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local" db, err := sql.Open("mysql", dsn) if err != nil { panic(err) } // ping是尝试连接MySQL数据库 if err = db.Ping(); err != nil { panic(err) } log.Println("连接成功") // 关闭连接 defer db.Close() }
代码解释
- 使用mysql驱动,必须引入
"github.com/go-sql-mysql/mysql"
dsn
:是待连接数据库信息。格式如下:
// username:password@[tcp(ip:port)]/dbname?charset=utf8mb4&parseTime=True&loc=Local // 用户名:密码@[协议(地址:端口)]/数据库名?charset=utf8mb4&parseTime=True&loc=Local dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
sql.Open()
:打开一个数据库
Ping()
:检验数据库连接是否有效
三、增删改查操作
1. 数据的增删改查
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" "log" ) var db *sql.DB // InitDB 数据库连接初始化 func InitDB() (err error) { dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse" db, err = sql.Open("mysql", dsn) CheckErr(err) err = db.Ping() CheckErr(err) fmt.Println("数据库连接成功...") // 设置数据库连接池最大连接数 db.SetConnMaxLifetime(10) //设置最大闲置连接数 db.SetMaxIdleConns(5) return } // CheckErr 统一处理错误 func CheckErr(err error) { if err != nil { fmt.Println(err) panic(err) } } type User struct { ID int32 Username string Password string Email string } func main() { if err := InitDB(); err != nil { fmt.Println("连接数据库失败") panic(err) } fmt.Println("接下来,请开始你的表演") }
func createUser(user User) { // 1. 写sql语句 sqlStr := "insert into user (username. password, email) values(?, ?, ?)" // 2. 执行sql语句 exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("新建数据失败") panic(err) } fmt.Println("新建数据成功") }
func createUser(user User) { // 1. 写sql语句 sqlStr := "insert into user (username. password, email) values(?, ?, ?)" // 2. 执行sql语句 exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("新建数据失败") panic(err) } fmt.Println("新建数据成功") }
func createUser(user User) { // 1. 写sql语句 sqlStr := "insert into user (username. password, email) values(?, ?, ?)" // 2. 执行sql语句 exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("新建数据失败") panic(err) } fmt.Println("新建数据成功") }
func deleteUser(id int) { // 1. 写sql语句 sqlStr := "delete from user where id = ?" // 2. 执行sql语句 exec, _ := db.Exec(sqlStr, id) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("删除数据失败") panic(err) } fmt.Println("删除数据成功") }
func updateUser(user User) { // 1. 写sql语句 sqlStr := "update user set username = ?, password = ? where id = ?" // 2. 执行sql语句 exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.ID) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("更新数据失败") panic(err) } fmt.Println("更新数据成功") }
func selectUserRow(id int32) { // 1. 写sql语句 sqlStr := "select * from user where id = ?" // 2. 执行sql语句 row := db.QueryRow(sqlStr, id) user := User{} err := row.Scan(&user.ID, &user.Username, &user.Password, &user.Email) if err != nil { fmt.Println("查询数据失败") panic(err) } fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email) }
func selectUserRows(id []int) { // 1. 写sql语句 sqlStr := "select * from user where id in (?)" // 2. 执行sql语句 rows, err := db.Query(sqlStr, id) if err != nil { fmt.Println("查询数据失败") panic(err) } for rows.Next() { user := User{} err := rows.Scan(&user.ID, &user.Username, &user.Password, &user.Email) if err != nil { fmt.Println("解析数据失败") panic(err) } fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email) } }
2. SQL的预处理
- 什么是预处理?
- 普通SQL语句的执行过程
- 客户端对SQL语句进行占位符的替换得到了完整的SQL语句
- 客户端发送完整SQL语句到MySQL服务端
- MySQL服务端执行完整的SQL语句并将结果返回终端
- 预处理的执行过程
- 先把SQL语句拆分成两部分,SQL语句部分和参数部分
- 先把SQL语句部分发送给MySQL服务端进行SQL预处理
- 然后参数部分发送给MySQL服务端,MySQL对SQL语句进行拼接
- MySQL服务端执行完整的SQL语句返回结果
- 普通SQL语句的执行过程
- 为什么要预处理
- 优化MySQL服务器重复执行SQL的方法。可以执行服务器的性能,提前让服务器编译,一次编译多次执行,节省后续重复编译的成本
- 避免SQL注入
对于go中操作数据库的预处理,方法是Proload,重要的是返回一个
Stmt
结构体的指针,和之前的DB
结构体一样的使用。
func preloadSelect(id int) { // 1. 写sql语句 sqlStr := "select * from user where id = ?" stmt, err := db.Prepare(sqlStr) if err != nil { fmt.Println("预处理sql语句失败") panic(err) } row := stmt.QueryRow(id) user := User{} err = row.Scan(&user.ID, &user.Username, &user.Password, &user.Email) if err != nil { fmt.Println("查询数据失败") panic(err) } fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email) }
3. SQL的事务
在go中开启数据库的事务主要就是三个函数:
Begin()
、Commit()
、RollBack()
func (db *DB) Begin()(*Tx, error)
:开启事务func (tx *Tx) Commit() error
:提交输入func (tx *Tx) Rollback() error
:事务回滚、
func TranSaCtIon() { // 开启事务 tx, err := db.Begin() if err != nil { fmt.Println("开启事务失败") panic(err) } // 执行多个SQL操作 sqlStr := "update test set id=id+100000 where password = ?" result, err := tx.Exec(sqlStr, "xcxcxc") if err != nil { fmt.Println("更新数据事变") panic(err) } id, err := result.LastInsertId() if err != nil { // 语句回滚 err := tx.Rollback() fmt.Println("事务回滚") if err != nil { fmt.Println("事务回滚失败失败") panic(err) } } fmt.Printf("修改后的id为%d\n", id) }
以上就是Go语言中database/sql的用法介绍的详细内容,更多关于Go语言 database/sql的资料请关注脚本之家其它相关文章!