Go语言入门(十) Mysql与Redis操作
时间:2022-07-25
本文章向大家介绍Go语言入门(十) Mysql与Redis操作,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Mysql与Redis操作
Mysql开发
- 安装mysql,创建test库
- 创建表
mysql> CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT '', `age` int(11) DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
mysql> insert into user (name,age)values('jim',18)
SQL查询
- 单行查询: Db.QueryRole
- 多行查询: Db.Query
import (
"fmt"
_"github.com/go-sql-driver/mysql"
"database/sql"
)
type User struct {
Id int64 `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
}
func connMysql() {
dns := "root:123456@tcp(localhost:3306)/test"
conn,err := sql.Open("mysql",dns)
if err != nil {
fmt.Printf("connect mysql err:%vn",err)
return
}
err = conn.Ping()
if err != nil {
fmt.Printf("ping faild,err :%vn",err)
}
fmt.Printf("connect mysql successfully!n")
QueryRow(conn)
Query(conn)
defer conn.Close()
}
func QueryRow(Db *sql.DB) {
id := 1
//单行数据查询
row := Db.QueryRow("select id,name,age from user where id=?",id)
var user User
err := row.Scan(&user.Id,&user.Name,&user.Age)
if err == sql.ErrNoRows {
fmt.Printf("not found data by id:%vn",id)
}
if err != nil {
fmt.Printf("scan faild,err: %vn",err)
return
}
fmt.Printf("user:%#vn",user)
}
func Query(Db *sql.DB) {
id := 0
//多行数据查询
rows,err := Db.Query("select id,name,age from user where id>?",id)
//一定要关闭结果集
defer func() {
if rows != nil {
rows.Close()
}
}()
//查询异常捕获
if err == sql.ErrNoRows {
fmt.Printf("not found data by id:%vn",id)
}
if err != nil {
fmt.Printf("scan faild,err: %vn",err)
return
}
//遍历所有数据
for rows.Next() {
var user User
err := rows.Scan(&user.Id,&user.Name,&user.Age)
if err == sql.ErrNoRows {
fmt.Printf("not found data by id:%vn",id)
}
if err != nil {
fmt.Printf("scan faild,err: %vn",err)
return
}
fmt.Printf("user:%#vn",user)
}
}
func main() {
connMysql()
}
Mysql插入更新和删除
- 使用DB.Exec()
import (
"fmt"
_"github.com/go-sql-driver/mysql"
"database/sql"
)
type User struct {
Id int64 `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
}
func Insert(DB *sql.DB) {
username := "alex"
age := 18
result,err := DB.Exec("insert into user(name,age) values(?,?)",username,age)
if err != nil {
fmt.Printf("sql exec insert faild:err:%vn",err)
return
}
id,err := result.LastInsertId()
if err != nil {
fmt.Printf("last insert id faild,err:%vn",err)
return
}
affectRows,err := result.RowsAffected()
if err != nil {
fmt.Printf("Rows affects faild,err:%vn",err)
return
}
fmt.Printf("last insert id:%d, affect rows:%dn",id,affectRows)
}
func Update(DB *sql.DB) {
username := "bbq"
age := 12
result,err := DB.Exec("update user set name=?,age=? where id=?",username,age,3)
if err != nil {
fmt.Printf("sql exec update faild:err:%vn",err)
return
}
affectRows,err := result.RowsAffected()
if err != nil {
fmt.Printf("Rows affects faild,err:%vn",err)
return
}
fmt.Printf("affect rows:%dn",affectRows)
}
func Delete(DB *sql.DB) {
id := 5
result,err := DB.Exec("delete from user where id=?",id)
if err != nil {
fmt.Printf("sql exec delete faild:err:%vn",err)
return
}
affectRows,err := result.RowsAffected()
if err != nil {
fmt.Printf("Rows affects faild,err:%vn",err)
return
}
fmt.Printf("affect rows:%dn",affectRows)
}
func connMysql() {
dns := "root:123456@tcp(localhost:3306)/test"
conn,err := sql.Open("mysql",dns)
if err != nil {
fmt.Printf("connect mysql err:%vn",err)
return
}
err = conn.Ping()
if err != nil {
fmt.Printf("ping faild,err :%vn",err)
}
fmt.Printf("connect mysql successfully!n")
//QueryRow(conn)
//Query(conn)
//Insert(conn)
//Update(conn)
Delete(conn)
defer conn.Close()
}
mysql预处理
- 一般sql处理流程
- 客户端拼接好sql语句
- 客户端发送sql语句到mysql服务器
- mysql服务器解析sql语句并执行,把输出结果返回给客户端
- 预处理流程
- 把sql拆分成两部分,命令部分和数据部分
- 首先把命令部分发送给mysql服务器,mysql进行sql预处理
- 然后把数据部分发送给mysql服务器,mysql进行占位符替换
- mysql执行sql语句并返回结果给客户端
- 预处理的优势
- 同一条sql反复执行,性能会很高
- 避免sql注入问题
预处理实例
- 查询操作
- Db.Prepare(sql string)(*sql.Stmt,error)
- Stmt.Query()
func PrepareQuery(DB *sql.DB) {
//第一部分:发送命令和占位符
stmt,err := DB.Prepare("select id,name,age from user where id>?")
if err != nil {
fmt.Printf("prepare faild,error:%vn",err)
return
}
//第二部分:发数据,并执行sql
id := 1
rows,err := stmt.Query(id)
//一定要关闭结果集
defer func() {
if rows != nil {
rows.Close()
}
if stmt != nil {
stmt.Close()
}
}()
//查询异常捕获
if err == sql.ErrNoRows {
fmt.Printf("not found data by id:%vn",id)
}
if err != nil {
fmt.Printf("scan faild,err: %vn",err)
return
}
//遍历所有数据
for rows.Next() {
var user User
err := rows.Scan(&user.Id,&user.Name,&user.Age)
if err == sql.ErrNoRows {
fmt.Printf("not found data by id:%vn",id)
}
if err != nil {
fmt.Printf("scan faild,err: %vn",err)
return
}
fmt.Printf("user:%#vn",user)
}
}
- 更新操作(插入,更新,delete)
- Db.Prepare(sql string)(*sql.Stmt,error)
- Stmt.Exec()
func PrepareInsert(DB *sql.DB) {
//第一部分:发送命令和占位符
stmt,err := DB.Prepare("insert into user (name,age) values (?,?);")
if err != nil {
fmt.Printf("prepare faild,error:%vn",err)
return
}
//第二部分:发数据,并执行sql
username := "zhangqiqi"
age := 29
result,err := stmt.Exec(username,age)
if err != nil {
fmt.Printf("sql exec insert faild:err:%vn",err)
return
}
id,err := result.LastInsertId()
if err != nil {
fmt.Printf("last insert id faild,err:%vn",err)
return
}
affectRows,err := result.RowsAffected()
if err != nil {
fmt.Printf("Rows affects faild,err:%vn",err)
return
}
fmt.Printf("last insert id:%d, affect rows:%dn",id,affectRows)
}
mysql事务实例
- 保证数据的一致性
- mysql的事务操作
- DB.Begin() 开启事务
- DB.Commit() 提交事务
- DB.Roback() 回滚事务
func Transaction(DB *sql.DB) {
tx,err := DB.Begin()
if err != nil {
fmt.Printf("begin faild,err:%vn",err)
return
}
_,err = tx.Exec("insert into user (name,age)values (?,?)","jemmy",80)
if err != nil {
tx.Rollback()
return
}
_,err = tx.Exec("update user set name=?,age=? where id=6","jemmxiny",60)
if err != nil {
tx.Rollback()
return
}
err = tx.Commit()
if err != nil {
tx.Rollback() //数据异常就回滚
return
}
}
sqlx库的介绍和使用
- sqlx的特点:
- 使用更简单
- 支持对数据库,mysql,postgresql,oracle,sqlit
- sqlx的使用
- 查询:sqlx.DB.Get和sqlx.DB.Select
- 更新,插入和删除: sqlx.DB.Exex()
- 事务:sqlx.DB.Begin(),sqlx.DB.Commit(),sqlx.DB.Rollback
go get github.com/jmoiron/sqlx
使用实例
import (
"database/sql"
"fmt"
"github.com/jmoiron/sqlx"
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int64 `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
}
func connMysql() {
dns := "root:123456@tcp(localhost:3306)/test"
conn,err := sqlx.Connect("mysql",dns)
if err != nil {
fmt.Printf("connect mysql err:%vn",err)
return
}
//超时测试
err = conn.Ping()
if err != nil {
fmt.Printf("ping faild,err :%vn",err)
}
fmt.Printf("connect mysql successfully!n")
//关闭连接
//QueryRow(conn)
//Query(conn)
Insert(conn)
defer conn.Close()
}
func QueryRow(Db *sqlx.DB) {
id := 100
//单行数据查询
var user User
err := Db.Get(&user,"select id,name,age from user where id=?",id)
//空行数据
if err == sql.ErrNoRows {
fmt.Printf("no record to foundn")
return
}
if err != nil {
fmt.Printf("get faild,err:%vn",err)
return
}
fmt.Printf("user:%#vn",user)
}
func Query(Db *sqlx.DB) {
var user []*User
id := 1
//多行数据查询
err := Db.Select(&user,"select id, name, age from user where id>?",id)
if err == sql.ErrNoRows {
fmt.Printf("no record foundn")
return
}
if err != nil {
fmt.Printf("select rows faild,err:%vn",err)
return
}
//输出查询结果
fmt.Printf("user:%#vn",user)
for _,v := range user {
fmt.Printf("%vn",v)
}
}
func Insert(Db *sqlx.DB) {
username := "alex"
age := 18
result,err := Db.Exec("insert into user(name,age) values(?,?)",username,age)
if err != nil {
fmt.Printf("sql exec insert faild:err:%vn",err)
return
}
id,err := result.LastInsertId()
if err != nil {
fmt.Printf("last insert id faild,err:%vn",err)
return
}
affectRows,err := result.RowsAffected()
if err != nil {
fmt.Printf("Rows affects faild,err:%vn",err)
return
}
fmt.Printf("last insert id:%d, affect rows:%dn",id,affectRows)
}
func main() {
connMysql()
}
Redis开发
- 使用第三方库:github.com/garyburd/redigo/redis
redis的使用
func initRedis() (conn redis.Conn,err error) {
conn,err = redis.Dial("tcp","127.0.0.1:6379")
if err != nil {
fmt.Printf("conn redis error:%vn",err)
return
}
fmt.Printf("conn redis succn")
return
}
func testSetGet(conn redis.Conn) {
key := "abc"
_,err := conn.Do("set",key,"this is a test!")
if err != nil {
fmt.Printf("set value faild,eror:%vn",err)
return
}
data,err := redis.String(conn.Do("get",key))
if err != nil {
fmt.Printf("get faild,err:%vn",err)
return
}
fmt.Printf("key:%s, value:%vn",key,data)
}
func main() {
conn,err := initRedis()
if err != nil {
return
}
testSetGet(conn)
}
Hash表操作
func testSetGet(conn redis.Conn) {
key := "abc"
_,err := conn.Do("hset","books",key,"this is a test!")
if err != nil {
fmt.Printf("set value faild,eror:%vn",err)
return
}
data,err := redis.String(conn.Do("hget","books",key))
if err != nil {
fmt.Printf("get faild,err:%vn",err)
return
}
fmt.Printf("key:%s, value:%vn",key,data)
}
Redis并发操作
func testMSetGet(conn redis.Conn) {
key := "abc"
key1 := "def"
_,err := conn.Do("mset",key,key1)
if err != nil {
fmt.Printf("set value faild,eror:%vn",err)
return
}
//多值操作返回的数据用strings接收
data,err := redis.Strings(conn.Do("mget",key,key1))
if err != nil {
fmt.Printf("get faild,err:%vn",err)
return
}
//循环取值
for _,val := range data {
fmt.Printf("key:%s, value:%vn",key,val)
}
}
设置队列
发布订阅
func testQuenu(conn redis.Conn) {
_,err := conn.Do("lpush","book_list","this is a test!","daadada")
if err != nil {
fmt.Printf("lpush value faild,eror:%vn",err)
return
}
data,err := redis.String(conn.Do("rpop","book_list"))
if err != nil {
fmt.Printf("get faild,err:%vn",err)
return
}
fmt.Printf("value:%sn",data)
}
连接池
func newPool(serverAddr string,passwd string) (pool *redis.Pool) {
return &redis.Pool{
MaxIdle: 16,
MaxActive: 1024,
IdleTimeout: 240,
Dial: func() (redis.Conn,error) {
conn,err := redis.Dial("tcp",serverAddr)
if err != nil {
return nil,err
}
if len(passwd) > 0 {
_,err := conn.Do("auth",passwd)
if err != nil {
return nil,err
}
}
return conn,err
},
TestOnBorrow: func(c redis.Conn,t time.Time) error {
if time.Since(t) < time.Minute {
return nil
}
_,err := c.Do("ping")
return err
},
}
}
func testRedisPool() {
pool := newPool("127.0.0.1:6379","")
conn := pool.Get()
conn.Do("set","abcd","23134534665437372132")
val,err := redis.String(conn.Do("get","abcd"))
if err != nil {
fmt.Printf("get faild,err:%vn",err)
}
fmt.Printf("val:%v,err:%vn",val,err)
//把连接归还到连接池
conn.Close()
}
- 数据库中间件mysql-proxy细节【mysql官方的中间件】
- Office CVE-2017-8570远程代码执行漏洞复现
- Java 并发包中的读写锁及其实现分析
- 深入理解 Spring 事务原理
- Chrome开发者工具的小技巧
- Java Web中JSP中6种动作概况知识点总结——每日一语法学习
- 从Flash到Silverlight进阶教程-用代码来创建动画
- 从Flash到Silverlight进阶教程-Tweener
- silverlight设置浏览器Cookies
- 一个最基本的布局控件-panel
- silverlight项目小结
- oozie 运行demo
- sqoop 兼容性问题
- oozie 安装过程详解
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解