golang 操作 MySQL 数据库总结
本文视频链接:https://www.bilibili.com/vide…
关注公众号,下载课程材料和源码:
筹备数据库和表
下载安装 MySQL
https://dev.mysql.com/downloads/mysql/
创立一个 go_db 数据库
create database go_db
关上数据库
use go_db
创立表
CREATE TABLE user_tbl (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
username VARCHAR (20),
PASSWORD VARCHAR (20)
)
增加模仿数据
INSERT INTO user_tbl (username, PASSWORD) VALUES ("tom", "123")
INSERT INTO user_tbl (username, PASSWORD) VALUES ("kite", "456")
装置配置 mysql 驱动
装置驱动
go get -u github.com/go-sql-driver/mysql
初始化模块
go mod init m
执行 go mod tidy
go mod tidy
导入驱动
package main
import (
"fmt"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func main() {}
取得数据库连贯
导入包
package main
import (
"fmt"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
取得连贯
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"time"
)
func main() {db, err := sql.Open("mysql", "root:123456@/go_db")
if err != nil {panic(err)
}
print(db)
// 最大连贯时长
db.SetConnMaxLifetime(time.Minute * 3)
// 最大连接数
db.SetMaxOpenConns(10)
// 闲暇连接数
db.SetMaxIdleConns(10)
}
初始化连贯
Open 函数可能只是验证其参数格局是否正确,实际上并不创立与数据库的连贯。如果要查看数据源的名称是否真实有效,应该调用 Ping 办法。
返回的 DB 对象能够平安地被多个 goroutine 并发应用,并且保护其本人的闲暇连接池。因而,Open 函数应该仅被调用一次,很少须要敞开这个 DB 对象。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
// 定义一个全局对象 db
var db *sql.DB
// 定义一个初始化数据库的函数
func initDB() (err error) {dsn := "root:123456@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4&parseTime=True"
// 不会校验账号密码是否正确
// 留神!!!这里不要应用:=,咱们是给全局变量赋值,而后在 main 函数中应用全局变量 db
db, err = sql.Open("mysql", dsn)
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("初始化失败!,err:%v\n", err)
return
}else{fmt.Printf("初始化胜利")
}
}
查问操作
单行查问
单行查问 db.QueryRow()
执行一次查问,并冀望返回最多一行后果(即 Row)。QueryRow 总是返回非 nil 的值,直到返回值的 Scan 办法被调用时,才会返回被提早的谬误。
定义一个构造体
type user struct {
id int
username string
password string
}
查问
// 查问一条用户数据
func queryRowDemo() {
sqlStr := "select id, username, password from user_tbl where id=?"
var u user
// 确保 QueryRow 之后调用 Scan 办法,否则持有的数据库链接不会被开释
err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.username, &u.password)
if err != nil {fmt.Printf("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d name:%s age:%s\n", u.id, u.username, u.password)
}
测试
func main() {err := initDB() // 调用输入化数据库的函数
if err != nil {fmt.Printf("初始化失败!,err:%v\n", err)
return
}else{fmt.Printf("初始化胜利")
}
queryRowDemo()}
运行后果
初始化胜利 id:1 name:tom age:123
查问多行
多行查问 db.Query()
执行一次查问,返回多行后果(即 Rows),个别用于执行 select 命令。参数 args 示意 query 中的占位参数。
// 查问多条数据示例
func queryMultiRow() {
sqlStr := "select id, username, password from user_tbl where id > ?"
rows, err := db.Query(sqlStr, 0)
if err != nil {fmt.Printf("query failed, err:%v\n", err)
return
}
// 十分重要:敞开 rows 开释持有的数据库链接
defer rows.Close()
// 循环读取后果集中的数据
for rows.Next() {
var u user
err := rows.Scan(&u.id, &u.username, &u.password)
if err != nil {fmt.Printf("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d username:%s password:%s\n", u.id, u.username, u.password)
}
}
运行后果
初始化胜利
id:1 username:tom password:123
id:2 username:kite password:456
插入数据
插入、更新和删除操作都应用 Exec
办法。
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
// 插入数据
func insertData() {sqlStr := "insert into user_tbl(username,password) values (?,?)"
ret, err := db.Exec(sqlStr, "张三", "zs123")
if err != nil {fmt.Printf("insert failed, err:%v\n", err)
return
}
theID, err := ret.LastInsertId() // 新插入数据的 id
if err != nil {fmt.Printf("get lastinsert ID failed, err:%v\n", err)
return
}
fmt.Printf("insert success, the id is %d.\n", theID)
}
测试
func main() {err := initDB() // 调用输入化数据库的函数
if err != nil {fmt.Printf("初始化失败!,err:%v\n", err)
return
}else{fmt.Printf("初始化胜利 \n")
}
//queryRowDemo()
//queryMultiRow()
insertData()}
运行后果
初始化胜利
insert success, the id is 3.
删除数据
插入、更新和删除操作都应用 Exec
办法。
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
删除
func delData() {
sql := "delete from user_tbl where id =?"
ret, err := db.Exec(sql, "1")
if err != nil {fmt.Printf("删除失败, err:%v\n", err)
return
}
rows, err := ret.RowsAffected()
if err != nil {fmt.Printf("删除行失败, err:%v\n", err)
return
}
fmt.Printf("删除胜利, 删除的行数:%d.\n", rows)
}
测试
func main() {err := initDB() // 调用输入化数据库的函数
if err != nil {fmt.Printf("初始化失败!,err:%v\n", err)
return
}else{fmt.Printf("初始化胜利 \n")
}
delData()}
运行后果
初始化胜利
删除胜利, 删除的行数:1.
更新数据
插入、更新和删除操作都应用 Exec
办法。
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
更新
func updateData() {
sql := "update user_tbl set username=?, password=? where id=?"
ret, err := db.Exec(sql, "kite2", "kite123", "2")
if err != nil {fmt.Printf("更新失败, err:%v\n", err)
return
}
rows, err := ret.RowsAffected()
if err != nil {fmt.Printf("更新行失败, err:%v\n", err)
return
}
fmt.Printf("更新胜利, 更新的行数:%d.\n", rows)
}
测试
func main() {err := initDB() // 调用输入化数据库的函数
if err != nil {fmt.Printf("初始化失败!,err:%v\n", err)
return
}else{fmt.Printf("初始化胜利 \n")
}
//queryRowDemo()
//queryMultiRow()
//insertData()
//delData()
updateData()}
运行后果
初始化胜利
更新胜利, 更新的行数:1.