Go使用Gin+Redis实现增删改查

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go使用Gin+Redis实现增删改查相关的知识,希望对你有一定的参考价值。

Go使用Gin+Redis实现增删改查

0.前置知识

  • Go中的struct。

  • Redis、Gin框架。

  • Web基础。

1.架构

使用Redis作为数据库,Gin作为Web框架。

2.功能模块

1.自定义Person结构体

2.实现对Person的增删改查。

  • 根据id查询或查询所有
  • 插入
  • 修改
  • 删除

3.实现流程

1.建立Redis数据库。

2.编写Web接口(增删改查)

3.通过postman测试或者直接网页请求测试。

4.代码

package main

// 导入模块
import (
	"bytes"
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	"log"
	"net/http"
	"strconv"
)

var db *sql.DB
var cnt int

// Person 自定义Person类
type Person struct 
	Id        int    `json:"id"`
	FirstName string `json:"first_name" form:"first_name"`
	LastName  string `json:"last_name" form:"last_name"`


func (g *Person) MarshalBinary() (data []byte, err error) 
	return json.Marshal(g)


func (g *Person) UnmarshalBinary(data []byte) (err error) 
	return json.Unmarshal(data, g)


func (p *Person) get(c *redis.Client, ctx *context.Context) (person Person, err error) 
	err = c.Get(*ctx, strconv.Itoa(p.Id)).Scan(p)
	if err != nil 
		log.Fatalln("get fail!")
		return
	
	person = *p
	return


func (p *Person) getAll(c *redis.Client, ctx *context.Context) (persons []Person, err error) 
	var ids []string
	ids, err = c.Keys(*ctx, "[1-9]*").Result()
	for _, id := range ids 
		myid, _ := strconv.Atoi(id)
		var person = Person
			Id: myid,
		
		person, _ = person.get(c, ctx)
		persons = append(persons, person)
	
	return


func (p *Person) add(c *redis.Client, ctx *context.Context) (Id int, err error) 
	// HMSet 批量设置 map[string]interface"age": 18, "sex": "male"
	cnt += 1
	Id = cnt
	p.Id = Id
	_, err = c.Set(*ctx, strconv.Itoa(cnt), p, 0).Result()
	if err != nil 
		return
	
	return


func (p *Person) update(c *redis.Client, ctx *context.Context) (rows int, err error) 
	if c.Exists(*ctx, strconv.Itoa(p.Id)).Val() == 1 
		_, err = c.Set(*ctx, strconv.Itoa(p.Id), p, 0).Result()
		if err != nil 
			return
		
		rows = 1
	
	return


func (p *Person) del(c *redis.Client, ctx *context.Context) (rows int, err error) 
	if c.Exists(*ctx, strconv.Itoa(p.Id)).Val() == 1 
		var my int64
		my, err = c.Del(*ctx, strconv.Itoa(p.Id)).Result()
		rows = int(my)
		if err != nil 
			return
		
	
	return


func test(db *sql.DB) 
	rows, err := db.Query("select * from person")
	if err != nil 
		return
	
	defer rows.Close()
	var persons []Person
	for rows.Next() 
		var person Person
		rows.Scan(&person.Id, &person.FirstName, &person.LastName)
		persons = append(persons, person)
	
	fmt.Println(persons)

func main() 
	ctx := context.Background()

	rdb := redis.NewClient(&redis.Options
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	)
	rdb.FlushDB(ctx)
	defer rdb.Close()
	_, err := rdb.Ping(ctx).Result() // PING, <nil>
	if err != nil 
		fmt.Println("connect redis failed:", err)
		return
	
	//创建路由引擎
	router := gin.Default()
	//查询,返回所有对象和对象个数
	router.GET("/persons", func(context *gin.Context) 
		p := Person
		persons, err := p.getAll(rdb, &ctx)
		if err != nil 
			log.Fatalln(err)
		
		context.JSON(http.StatusOK, gin.H
			"result": persons,
			"count":  len(persons),
		)
	)

	//根据id查询
	router.GET("/person/:id", func(context *gin.Context) 
		var result gin.H
		id := context.Param("id")

		Id, err := strconv.Atoi(id)
		if err != nil 
			log.Fatalln(err)
		
		p := Person
			Id: Id,
		
		person, err := p.get(rdb, &ctx)
		if err != nil 
			result = gin.H
				"result": nil,
				"count":  0,
			
		 else 
			result = gin.H
				"result": person,
				"count":  1,
			
		
		context.JSON(http.StatusOK, result)
	)

	//创建person
	router.POST("/person", func(context *gin.Context) 
		var p Person
		err := context.Bind(&p)
		if err != nil 
			log.Fatalln(err)
		

		Id, err := p.add(rdb, &ctx)
		if err != nil 
			log.Fatalln(err)
		
		fmt.Println(Id)
		name := p.FirstName + " " + p.LastName
		context.JSON(http.StatusOK, gin.H
			"message": fmt.Sprintf(" %s 成功创建", name),
		)
	)

	//更新update
	router.PUT("/person/:id", func(context *gin.Context) 
		var (
			p      Person
			buffer bytes.Buffer
		)

		id := context.Param("id")
		Id, err := strconv.Atoi(id)
		if err != nil 
			log.Fatalln(err)
		
		err = context.Bind(&p)
		if err != nil 
			log.Fatalln(err)
		
		p.Id = Id
		rows, err := p.update(rdb, &ctx)
		if err != nil 
			log.Fatalln(err)
		
		fmt.Println(rows)
		buffer.WriteString(p.FirstName)
		buffer.WriteString(" ")
		buffer.WriteString(p.LastName)
		name := buffer.String()

		context.JSON(http.StatusOK, gin.H
			"message": fmt.Sprintf("成功更新到%s", name),
		)
	)

	//删除person
	router.DELETE("/person/:id", func(context *gin.Context) 
		id := context.Param("id")

		Id, err := strconv.ParseInt(id, 10, 10)
		if err != nil 
			log.Fatalln(err)
		
		p := PersonId: int(Id)
		rows, err := p.del(rdb, &ctx)
		if err != nil 
			log.Fatalln(err)
		
		fmt.Println("delete rows: ", rows)

		context.JSON(http.StatusOK, gin.H
			"message": fmt.Sprintf("成功删除用户:%s", id),
		)
	)
	router.Run(":8080")


5.结果



6.总结

6.1 对于复杂类型如struct,存储时需要进行序列化和反序列化。

具体来说就是重载序列化和反序列化这两个函数。

func (g *Person) MarshalBinary() (data []byte, err error) 
	return json.Marshal(g)


func (g *Person) UnmarshalBinary(data []byte) (err error) 
	return json.Unmarshal(data, g)

不然会出现下面的报错

can’t marshal *main.Person (implement encoding.BinaryMarshaler)


6.2 因为Redis的key都是string类型,所以需要用到int和string类型的转换。

可以使用strconv包的Itoa和Atoi

str = strconv.Itoa(p.Id) //int -> string
p.Id = strconv.Atoi(str) //string -> int

6.3 因为Redis的Set 不存在就插入,存在就覆盖。

所以Set函数可以实现插入和更新两个操作。

6.4 Redis进行keys的模糊查询时,只有*,[],?这三种。

不能使用\\d这种,所以怎么样实现正整数的匹配,有待商榷qwq。

以上是关于Go使用Gin+Redis实现增删改查的主要内容,如果未能解决你的问题,请参考以下文章

Redis的增删改查持久化你会了吗

Redis的增删改查命令总结与持久化方式

Redis从认识安装到实现增删改查

Beego脱坑(十三)ORM基本增删改查

Redis之java增删改查

Redis之java增删改查