前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >gin操作MySQL和Redis

gin操作MySQL和Redis

作者头像
是小张啊喂
发布2021-08-10 11:29:09
2.6K0
发布2021-08-10 11:29:09
举报
文章被收录于专栏:软件软件

go这些基础的东西,看起来很舒服,最起码对于写习惯java的人来讲,go真的很舒服,所以近一段时间可能一直连更,gin并没有直接封装操作MySQL的工具类,所以还是使用开源的工具

代码语言:javascript
复制
github.com/garyburd/redigo v1.6.2
github.com/go-sql-driver/mysql v1.5.0
github.com/jmoiron/sqlx v1.2.0
go操作mysql数据库

当前代码文件结构

代码语言:javascript
复制
|- mian.go
|- app 
|	|- api
|		|- student_api.go
|	|- model
|		|- student
|			|- student.go
|- routers
|	|- routers.go
|- util
|	|- util.go
新建 myschool数据库,以及student
代码语言:javascript
复制
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` varchar(225) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `name` varchar(225) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
获取数据库连接

对比goframe框架的话,gin看起来不是很整洁,因为没有封装操作数据库的工具,所以我们只能用原生的代码来操作,需要写死配置,对比JavaSpringBoot确实差一点,但是对比JDBC的话,go可就好太多了

这里的话,新建util.go用于获取数据库连接,将路由、功能、工具区分开

代码语言:javascript
复制
var Db *sqlx.DB

func Init() {
	// 获取 MySQL 链接需要自己导入 _ "github.com/go-sql-driver/mysql" 
	database, err := sqlx.Open("mysql", "root:Root5683@@tcp(127.0.0.1:3306)/myschool")
	//database, err := sqlx.Open("数据库类型", "用户名:密码@tcp(地址:端口)/数据库名")
	if err != nil {
		fmt.Println("open mysql failed,", err)
		return
	}

	Db = database
	// 关闭数据库连接
	//defer database.Close() // 注意这行代码要写在上面err判断的下面
}

连接创建完成下一步,我们需要创建路由,这里选择分组路由,方便后面继续做拓展

创建路由

创建routers.go

代码语言:javascript
复制
func Router() *gin.Engine {
	r := gin.Default()
	// 初始化数据连接
	util.Init()
	s := r.Group("/student")
	{
		s.PUT("/save", api.Save)
		s.GET("/select", api.SelectById)
		s.POST("/update", api.Update)
		s.DELETE("/delete", api.Delete)
	}
	return r
}

启动类肯定是必不可少的,接下来看下一下main.go

代码语言:javascript
复制
func main() {
	// 加载路由
	r := routers.Router()
    // 默认端口:8080
	r.Run()
}

结构实体肯定是必不可少的,student.go,这里就要夸一夸goframe框架了,可以自动生成,但是没有的话,自己麻烦一点,也就麻烦那一下,也不是说很多个字段那么夸张

代码语言:javascript
复制
type Student struct {
	Id   string `orm:"id,primary" json:"id"`
	Name string `orm:"name"       json:"name"`
	Age  int    `orm:"age"        json:"age"`
}
crud

准备工作做好,下面就是重点了,对student表进行操作crud,接口测试使用Postman

代码语言:javascript
复制
// 新增学生
/*
http://127.0.0.1:8080/student/save
{
   "id":"1",
   "name":"chenghao_",
   "age":30
}
*/
func Save(c *gin.Context) {
	// 获取传递的参数 转换成 struct
	var stu student.Student
	if err := c.ShouldBindJSON(&stu); err != nil {
		// 返回错误信息
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	result, err := util.Db.Exec("insert into student(id,name,age) values(?,?,?)", stu.Id, stu.Name, stu.Age)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	log.Println(result)
	c.JSON(http.StatusOK, gin.H{"success": "添加成功"})
}

// 根据 id 查询
/*
http://127.0.0.1:8080/student/select?id=1
*/
func SelectById(c *gin.Context) {
	var stu []student.Student
	// 获取查询参数
	id := c.Query("id")
	err := util.Db.Select(&stu, "select id,name,age from student where id =?", id)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"success": stu})
}

// 修改
/*
http://127.0.0.1:8080/student/update
{
   "id":"1",
   "name":"chenghao_",
   "age":19
}
*/
func Update(c *gin.Context) {
	// 获取传递的参数 转换成你 struct
	var stu student.Student
	if err := c.ShouldBindJSON(&stu); err != nil {
		// 返回错误信息
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	result, err := util.Db.Exec("update student set name=?,age=? where id=?", stu.Name, stu.Age, stu.Id)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	log.Println(result)
	c.JSON(http.StatusOK, gin.H{"success": "修改成功"})
}

// 删除
/*
http://127.0.0.1:8080/student/select?id=1
*/
func Delete(c *gin.Context) {
	// 获取查询参数
	id := c.Query("id")
	result, err := util.Db.Exec("delete from student where id =?", id)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"success": result})
}

go也相应的支持MySQL事务,看业务逻辑自行调用

代码语言:javascript
复制
1. Db.Begin()        开始事务
2. Db.Commit()        提交事务
3. Db.Rollback()     回滚事务
go操作Redis

Redis 高性能的key-value数据库,需要了解的自行学习,这里只做简单的使用

获取数据链接

代码语言:javascript
复制
func main() {
    c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		log.Println("conn redis failed,", err)
		return
	}
}
String类型

使用c.Do(commandName string, args ...interface{})向服务器发送命令并返回收到的答复,低一个是操作名称,这个和redis原生命令有点像,只是命令首字母是大写的,javajedis有点类似,只是jedis是直接点set()方法,且首字母小写

redis操作String类型,

代码语言:javascript
复制
func main() {
    // 获取操作redis的链接
    c, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		log.Println("conn redis failed,", err)
		return
	}

    // 设置一个key为name 值为Shao Jie
	_, err = c.Do("Set", "name", "Shao Jie")
	if err != nil {
		log.Println(err.Error())
		return
	}
	// 取值 取一个key为name的值
	name, err := redis.String(c.Do("Get", "name"))
	if err != nil {
		log.Println(err.Error())
		return
	}
	log.Println(name)
}

需要注意一个问题,c.Do方法在操作Get的时候,会出现乱码,这里用redis.String转了一下类型,正常输出,如果是一个数字类型可以调用redis.Int

批量操作String类型
代码语言:javascript
复制
// 设置一个key是name一个为age 值为Shao Jie、21
_, err = c.Do("MSet", "name", "shaojie_", "age", 21)
if err != nil {
    log.Println(err.Error())
    return
}

// 取值 取一个key为name一个为age的值
result, err := redis.Strings(c.Do("MGet", "name", "age"))
if err != nil {
    log.Println("get name failed,", err)
    return
}

for _, v := range result {
    log.Println(v)
}

需要注意,这里我们取值的时候取的是批量的,所以,这里要注意转型redis.Strings,数字类型调用redis.Ints

设置过期时间
代码语言:javascript
复制
// 设置一个key为name 值为shaojie_
_, err = c.Do("Set", "name", "shaojie_")
if err != nil {
    log.Println(err.Error())
    return
}

// 设置过期时间 10 为秒
_, err = c.Do("expire", "name", 10)
if err != nil {
    fmt.Println(err)
    return
}

// 取值 取一个key为name的值
name, err := redis.String(c.Do("Get", "name"))
if err != nil {
    log.Println(err.Error())
    return
}
log.Println(name)

// 休眠十秒
time.Sleep(10 * time.Second)

// 取值  十秒取一个key为name的值
name1, err := redis.String(c.Do("Get", "name"))
if err != nil {
    log.Println(err.Error())
    return
}
log.Println(name1)

这里显得比java要麻烦一些,需要单独使用expire为特定的key设置过期时间,单位是秒

list类型
代码语言:javascript
复制
// 设置一个key为namelist 值为shaojie_ 、chenghao_
_, err = c.Do("lpush", "namelist", "shaojie_","chenghao_")
if err != nil {
    log.Println(err.Error())
    return
}

// 取值 获取一个值为 namelist的值 获取这个值之后会删除这个值
namelist, err := redis.String(c.Do("lpop", "namelist"))
if err != nil {
    log.Println("get namelist failed,", err)
    return
}

log.Println(namelist)
hash类型
代码语言:javascript
复制
// 设置 shaojie_ 的年龄age为21
_, err = c.Do("HSet", "shaojie_", "age", 21)
if err != nil {
    log.Println(err)
    return
}

// 获取 shaojie_ 的年龄age
age, err := redis.Int(c.Do("HGet", "shaojie_", "age"))
if err != nil {
    fmt.Println("get shaojie_'s age failed,", err)
    return
}

log.Println(age)

以上三种类型是我们常会用到的,后面都需要获取redis的连接显得有些麻烦,不可能每次使用都去连接一次,如果想像操作mysql一样只获取一次,然后直接可以在别得地方调用,那就很舒服,所以,可以借用redis连接池

redis连接池

获取redis连接池,这个我们同样在util.go中得Init方法中调用

代码语言:javascript
复制
var Pool *redis.Pool //创建redis连接池

func Init() {
	Pool = &redis.Pool{ //实例化一个连接池
		MaxIdle: 16, //最初的连接数量
		// MaxActive:1000000,    //最大连接数量
		MaxActive:   0,   //连接池最大连接数量,不确定可以用0(0表示自动定义),按   需分配
		IdleTimeout: 300, //连接关闭时间 300秒 (300秒不使用自动关闭)
		Dial: func() (redis.Conn, error) { //要连接的redis数据库
			return redis.Dial("tcp", "127.0.0.1:6379")
		},
	}
}

创建好工具后,需要在系统启动时调用,去创建连接池,然后再以hash类型举例,获取在上面设置好的一个key的值

代码语言:javascript
复制
func main() {
    // 初始化工具的连接
	util.Init()
	c := util.Pool.Get() //从连接池,取一个链接
	defer c.Close() //函数运行结束 ,把连接放回连接池

    // 拿key为shaojie_的age的具体值
	r, err := redis.Int(c.Do("HGet", "shaojie_","age"))
	if err != nil {
		fmt.Println("get abc faild :", err)
		return
	}
	log.Println(r)
	util.Pool.Close() //关闭连接池
}

这一整个的流程文档讲的还算比较清楚,对比java学习事半功倍,最近学习起来感觉极其上瘾,但是平常公司有点小忙,也算是忙里偷闲去学习,多学习才会有更多的选择,学无止境,苦海无涯

借鉴一位学长的话:

每天要学两个小时。 --小石头

这句话其实给我说了很久,我很少有机会去做,但是却没有忘记,没有理由没有借口,如果习惯去找借口,那学习这件事情不如就此放弃,共勉!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • go操作mysql数据库
    • 新建 myschool数据库,以及student表
      • 获取数据库连接
        • 创建路由
          • crud
          • go操作Redis
            • String类型
              • 批量操作String类型
                • 设置过期时间
                  • list类型
                    • hash类型
                      • redis连接池
                      相关产品与服务
                      云数据库 Redis
                      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档