Go+Redis零基础到用户管理系统API实战_20240730 课程笔记
概述
如果您没有Golang的基础,应该学习如下前置课程。
- Golang零基础入门
- Golang面向对象编程
- Go Web 基础
- Go语言开发REST API接口_20240728
- Go语言操作MySQL开发用户管理系统API教程_20240729
- Redis零基础快速入门_20231227
基础不好的同学每节课的代码最好配合视频进行阅读和学习,如果基础比较扎实,则阅读本教程巩固一下相关知识点即可,遇到不会的知识点再看视频。
视频课程
最近发现越来越多的公司在用Golang了,所以精心整理了一套视频教程给大家,这个是其中的第6部,后续还会有很多。
视频已经录制完成,完整目录截图如下:
本套课程的特色是每节课都是一个核心知识点,每个视频控制在十分钟左右,精简不废话,拒绝浪费大家的时间。
课程目录
- 01 概述
- 02 建立Redis连接对象
- 03 edis的打开和关闭方法
- 04 通过Do执行get和set命令
- 05 通过String自动转换字符串
- 06 通过Do实现mset和mget的操作
- 07 通过Do实现hset和hget的操作
- 08 通过Do实现lpush和lpop以及llen的操作
- 09 Redis的连接池介绍
- 10 Redis连接池的创建和使用
- 11 Redis的管道操作
- 12 Redis的事务操作
- 13 实现redigo的本地化
- 14 对zdpgo_redis的包结构进行调整
- 15 发布zdpgo_redisv1.1.0版本
- 16 新增用户
- 17 修改用户
- 18 删除用户
- 19 查询所有用户
- 20 实现查询所有用户的接口并进行测试
- 21 实现新增用户的接口并进行测试
- 22 解决ID唯一性的问题
- 23 实现修改用户的接口并进行测试
- 24 实现删除用户的接口并进行测试
- 25 实现根据ID查询用户的接口并进行测试
- 26 总结
完整代码
01 概述
02 建立Redis连接对象
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)func main() {r, err := redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println(err)return}defer r.Close()
}
03 edis的打开和关闭方法
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (r redis.Connerr error
)func InitRedis() {r, err = redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println(err)return}
}func CloseRedis() {r.Close()
}func main() {InitRedis()defer CloseRedis()fmt.Println("主程序的操作。。。")
}
04 通过Do执行get和set命令
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (r redis.Connerr error
)func InitRedis() {r, err = redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println(err)return}
}func CloseRedis() {r.Close()
}func main() {InitRedis()defer CloseRedis()// set 操作_, err = r.Do("SET", "name", "张三")if err != nil {fmt.Println(err)return}// get 操作var reply interface{}reply, err = r.Do("GET", "name")if err != nil {fmt.Println(err)return}fmt.Println(string(reply.([]byte)))
}
05 通过String自动转换字符串
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (r redis.Connerr error
)func InitRedis() {r, err = redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println(err)return}
}func CloseRedis() {r.Close()
}func main() {InitRedis()defer CloseRedis()// set 操作_, err = r.Do("SET", "name", "张三")if err != nil {fmt.Println(err)return}// get 操作var reply stringreply, err = redis.String(r.Do("GET", "name"))if err != nil {fmt.Println(err)return}fmt.Println(reply)
}
06 通过Do实现mset和mget的操作
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (r redis.Connerr error
)func InitRedis() {r, err = redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println(err)return}
}func CloseRedis() {r.Close()
}func main() {InitRedis()defer CloseRedis()// set 操作// 也一定要注意,是:key1,value1,key2,value2... 的格式_, err = r.Do("MSET", "name", "张三", "age", 22, "gender", "男")if err != nil {fmt.Println(err)return}// get 操作// 这个传递的是想要哪些keyvar reply []stringreply, err = redis.Strings(r.Do("MGET", "name", "age", "gender"))if err != nil {fmt.Println(err)return}fmt.Println(reply)
}
07 通过Do实现hset和hget的操作
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (r redis.Connerr error
)func InitRedis() {r, err = redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println(err)return}
}func CloseRedis() {r.Close()
}func main() {InitRedis()defer CloseRedis()_, err = r.Do("HSET", "user", "name", "张三")if err != nil {fmt.Println(err)return}var reply stringreply, err = redis.String(r.Do("HGET", "user", "name"))if err != nil {fmt.Println(err)return}fmt.Println(reply)
}
08 通过Do实现lpush和lpop以及llen的操作
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (r redis.Connerr error
)func InitRedis() {r, err = redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println(err)return}
}func CloseRedis() {r.Close()
}func main() {InitRedis()defer CloseRedis()_, err = r.Do("LPUSH", "arr", "张三", "李四", "王五")if err != nil {fmt.Println(err)return}var reply stringreply, err = redis.String(r.Do("LPOP", "arr"))if err != nil {fmt.Println(err)return}fmt.Println(reply)var length intlength, err = redis.Int(r.Do("LLEN", "arr"))if err != nil {fmt.Println(err)return}fmt.Println(length)}
09 Redis的连接池介绍
10 Redis连接池的创建和使用
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (pool *redis.Poolerr error
)func InitRedis() {pool = &redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (redis.Conn, error) {return redis.Dial("tcp", "127.0.0.1:6379")},}
}func main() {InitRedis()r := pool.Get()defer r.Close()_, err = r.Do("LPUSH", "arr", "张三", "李四", "王五")if err != nil {fmt.Println(err)return}var reply stringreply, err = redis.String(r.Do("LPOP", "arr"))if err != nil {fmt.Println(err)return}fmt.Println(reply)var length intlength, err = redis.Int(r.Do("LLEN", "arr"))if err != nil {fmt.Println(err)return}fmt.Println(length)}
11 Redis的管道操作
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (pool *redis.Poolerr error
)func InitRedis() {pool = &redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (redis.Conn, error) {return redis.Dial("tcp", "127.0.0.1:6379")},}
}func main() {InitRedis()r := pool.Get()defer r.Close()// 写入缓冲r.Send("SET", "name1", "张三")r.Send("SET", "name2", "李四")// 清空缓冲,写入服务端(Redis)r.Flush()// 读取:先进先出receive, err := r.Receive()fmt.Printf("receive:%#v, err:%v\n", receive, err)receive, err = r.Receive()fmt.Printf("receive:%#v, err:%v\n", receive, err)// 因为没有数据了,所以会一直处于等待状态receive, err = r.Receive()fmt.Printf("receive:%#v, err:%v\n", receive, err)
}
12 Redis的事务操作
package mainimport ("fmt""github.com/gomodule/redigo/redis"
)var (pool *redis.Poolerr error
)func InitRedis() {pool = &redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (redis.Conn, error) {return redis.Dial("tcp", "127.0.0.1:6379")},}
}func main() {InitRedis()r := pool.Get()defer r.Close()r.Send("MULTI") // 开启事务// 事务过程中的一些业务操作r.Send("INCR", "num1")r.Send("INCR", "num2")reply, err := r.Do("EXEC") // 执行事务fmt.Printf("%#v err:%v\n", reply, err)
}
13 实现redigo的本地化
14 对zdpgo_redis的包结构进行调整
15 发布zdpgo_redisv1.1.0版本
16 新增用户
package mainimport ("encoding/json""fmt""github.com/zhangdapeng520/zdpgo_redis"
)var (pool *zdpgo_redis.Poolerr error
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}type User struct {Id int `json:"id"`Name string `json:"name"`Age int `json:"age"`
}func main() {InitRedis()r := pool.Get()defer r.Close()// string hash list// string hash users:{1:{id:1,xxx},2:xxx}// string 代码会更简单zs := User{2, "李四", 23}key := fmt.Sprintf("user/%d", zs.Id)zsBytes, _ := json.Marshal(zs)value := string(zsBytes)r.Do("SET", key, value)value2, _ := zdpgo_redis.String(r.Do("GET", key))fmt.Println(value2)
}
17 修改用户
package mainimport ("encoding/json""fmt""github.com/zhangdapeng520/zdpgo_redis"
)var (pool *zdpgo_redis.Poolerr error
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}type User struct {Id int `json:"id"`Name string `json:"name"`Age int `json:"age"`
}func main() {InitRedis()r := pool.Get()defer r.Close()id := 1name := "李四"// 查询key := fmt.Sprintf("user/%d", id)value2, _ := zdpgo_redis.String(r.Do("GET", key))fmt.Println(value2)// 解析var user Userjson.Unmarshal([]byte(value2), &user)fmt.Println(user)// 修改user.Name = name// 重新存储jsonBytes, _ := json.Marshal(user)fmt.Println(string(jsonBytes))r.Do("SET", key, string(jsonBytes))
}
18 删除用户
package mainimport ("fmt""github.com/zhangdapeng520/zdpgo_redis"
)var (pool *zdpgo_redis.Poolerr error
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}type User struct {Id int `json:"id"`Name string `json:"name"`Age int `json:"age"`
}func main() {InitRedis()r := pool.Get()defer r.Close()id := 1// 查询key := fmt.Sprintf("user/%d", id)value2, _ := zdpgo_redis.String(r.Do("GET", key))fmt.Println(value2)// 删除r.Do("DEL", key)// 再查询value2, _ = zdpgo_redis.String(r.Do("GET", key))fmt.Println(value2)
}
19 查询所有用户
package mainimport ("encoding/json""fmt""github.com/zhangdapeng520/zdpgo_redis"
)var (pool *zdpgo_redis.Poolerr error
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}type User struct {Id int `json:"id"`Name string `json:"name"`Age int `json:"age"`
}func main() {InitRedis()r := pool.Get()defer r.Close()// 获取所有的keyuserKeys, _ := zdpgo_redis.Strings(r.Do("KEYS", "user/*"))fmt.Println(userKeys)// 查询var users []Userfor _, key := range userKeys {var user UseruserStr, _ := zdpgo_redis.String(r.Do("GET", key))json.Unmarshal([]byte(userStr), &user)users = append(users, user)}fmt.Println(users)
}
20 实现查询所有用户的接口并进行测试
package mainimport ("encoding/json""github.com/zhangdapeng520/zdpgo_httprouter""github.com/zhangdapeng520/zdpgo_redis""net/http""time"
)type User struct {Id int `json:"id"`Name string `json:"name"`Age int `json:"age"`
}var (pool *zdpgo_redis.Pool
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}func RouterGetUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()// 获取所有的keyuserKeys, _ := zdpgo_redis.Strings(rdb.Do("KEYS", "user/*"))// 查询var users []Userfor _, key := range userKeys {var user UseruserStr, _ := zdpgo_redis.String(rdb.Do("GET", key))json.Unmarshal([]byte(userStr), &user)users = append(users, user)}zdpgo_httprouter.ResponseSuccess(w, users)
}func main() {InitRedis()router := zdpgo_httprouter.New()router.GET("/user", RouterGetUser)server := &http.Server{Addr: "0.0.0.0:8888",Handler: router,ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,}server.ListenAndServe()
}
package mainimport ("fmt""io""net/http"
)func main() {resp, err := http.Get("http://localhost:8888/user")if err != nil {fmt.Println(err)return}body := resp.BodybodyBytes, err := io.ReadAll(body)if err != nil {fmt.Println(err)return}fmt.Println(string(bodyBytes))
}
21 实现新增用户的接口并进行测试
package mainimport ("encoding/json""fmt""github.com/zhangdapeng520/zdpgo_httprouter""github.com/zhangdapeng520/zdpgo_redis""net/http""time"
)type User struct {Id int `json:"id"`Name string `json:"name"`Age int `json:"age"`
}var (pool *zdpgo_redis.Pool
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}func RouterGetUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()// 获取所有的keyuserKeys, _ := zdpgo_redis.Strings(rdb.Do("KEYS", "user/*"))// 查询var users []Userfor _, key := range userKeys {var user UseruserStr, _ := zdpgo_redis.String(rdb.Do("GET", key))json.Unmarshal([]byte(userStr), &user)users = append(users, user)}zdpgo_httprouter.ResponseSuccess(w, users)
}func RouterAddUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var user Userzdpgo_httprouter.GetJson(r, &user)id := time.Now().Nanosecond()user.Id = id// 新增key := fmt.Sprintf("user/%d", user.Id)zsBytes, _ := json.Marshal(user)value := string(zsBytes)rdb.Do("SET", key, value)// 返回zdpgo_httprouter.ResponseSuccess(w, user)
}func main() {InitRedis()router := zdpgo_httprouter.New()router.POST("/user", RouterAddUser)router.GET("/user", RouterGetUser)server := &http.Server{Addr: "0.0.0.0:8888",Handler: router,ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,}server.ListenAndServe()
}
package mainimport ("fmt""github.com/zhangdapeng520/zdpgo_httprouter""io"
)func main() {targetUrl := "http://localhost:8888/user"data := map[string]interface{}{"name": "王五","age": 35,}resp, err := zdpgo_httprouter.SendJson("POST", targetUrl, data)if err != nil {fmt.Println(err)return}body := resp.BodybodyBytes, err := io.ReadAll(body)if err != nil {fmt.Println(err)return}fmt.Println(string(bodyBytes))
}
22 解决ID唯一性的问题
package mainimport ("encoding/json""fmt""github.com/zhangdapeng520/zdpgo_httprouter""github.com/zhangdapeng520/zdpgo_redis""net/http""time"
)type User struct {Id int64 `json:"id"`Name string `json:"name"`Age int `json:"age"`
}var (pool *zdpgo_redis.Pool
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}func RouterGetUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()// 获取所有的keyuserKeys, _ := zdpgo_redis.Strings(rdb.Do("KEYS", "user/*"))// 查询var users []Userfor _, key := range userKeys {var user UseruserStr, _ := zdpgo_redis.String(rdb.Do("GET", key))json.Unmarshal([]byte(userStr), &user)users = append(users, user)}zdpgo_httprouter.ResponseSuccess(w, users)
}func RouterAddUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var user Userzdpgo_httprouter.GetJson(r, &user)id := time.Now().UnixNano()user.Id = id// 新增key := fmt.Sprintf("user/%d", user.Id)zsBytes, _ := json.Marshal(user)value := string(zsBytes)rdb.Do("SET", key, value)// 返回zdpgo_httprouter.ResponseSuccess(w, user)
}func main() {InitRedis()router := zdpgo_httprouter.New()router.POST("/user", RouterAddUser)router.GET("/user", RouterGetUser)server := &http.Server{Addr: "0.0.0.0:8888",Handler: router,ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,}server.ListenAndServe()
}
package mainimport ("fmt""github.com/zhangdapeng520/zdpgo_httprouter""io"
)func main() {targetUrl := "http://localhost:8888/user"data := map[string]interface{}{"name": "王五","age": 35,}resp, err := zdpgo_httprouter.SendJson("POST", targetUrl, data)if err != nil {fmt.Println(err)return}body := resp.BodybodyBytes, err := io.ReadAll(body)if err != nil {fmt.Println(err)return}fmt.Println(string(bodyBytes))
}
23 实现修改用户的接口并进行测试
package mainimport ("encoding/json""fmt""github.com/zhangdapeng520/zdpgo_httprouter""github.com/zhangdapeng520/zdpgo_redis""net/http""time"
)type User struct {Id int64 `json:"id"`Name string `json:"name"`Age int `json:"age"`
}var (pool *zdpgo_redis.Pool
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}func RouterGetUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()// 获取所有的keyuserKeys, _ := zdpgo_redis.Strings(rdb.Do("KEYS", "user/*"))// 查询var users []Userfor _, key := range userKeys {var user UseruserStr, _ := zdpgo_redis.String(rdb.Do("GET", key))json.Unmarshal([]byte(userStr), &user)users = append(users, user)}zdpgo_httprouter.ResponseSuccess(w, users)
}func RouterAddUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var user Userzdpgo_httprouter.GetJson(r, &user)id := time.Now().UnixNano()user.Id = id// 新增key := fmt.Sprintf("user/%d", user.Id)zsBytes, _ := json.Marshal(user)value := string(zsBytes)rdb.Do("SET", key, value)// 返回zdpgo_httprouter.ResponseSuccess(w, user)
}func RouterUpdateUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var user Uservar idStr = ps.ByName("id")zdpgo_httprouter.GetJson(r, &user)// 查询key := fmt.Sprintf("user/%s", idStr)userJson, _ := zdpgo_redis.String(rdb.Do("GET", key))// 解析var dbUser Userjson.Unmarshal([]byte(userJson), &dbUser)// 修改dbUser.Name = user.NamedbUser.Age = user.Age// 重新存储jsonBytes, _ := json.Marshal(dbUser)rdb.Do("SET", key, string(jsonBytes))// 返回zdpgo_httprouter.ResponseSuccess(w, dbUser)
}func main() {InitRedis()router := zdpgo_httprouter.New()router.POST("/user", RouterAddUser)router.GET("/user", RouterGetUser)router.PUT("/user/:id", RouterUpdateUser)server := &http.Server{Addr: "0.0.0.0:8888",Handler: router,ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,}server.ListenAndServe()
}
package mainimport ("fmt""github.com/zhangdapeng520/zdpgo_httprouter""io"
)func main() {targetUrl := "http://localhost:8888/user/108534300"data := map[string]interface{}{"name": "王六","age": 35,}resp, err := zdpgo_httprouter.SendJson("PUT", targetUrl, data)if err != nil {fmt.Println(err)return}body := resp.BodybodyBytes, err := io.ReadAll(body)if err != nil {fmt.Println(err)return}fmt.Println(string(bodyBytes))
}
24 实现删除用户的接口并进行测试
package mainimport ("encoding/json""fmt""github.com/zhangdapeng520/zdpgo_httprouter""github.com/zhangdapeng520/zdpgo_redis""net/http""time"
)type User struct {Id int64 `json:"id"`Name string `json:"name"`Age int `json:"age"`
}var (pool *zdpgo_redis.Pool
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}func RouterGetUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()// 获取所有的keyuserKeys, _ := zdpgo_redis.Strings(rdb.Do("KEYS", "user/*"))// 查询var users []Userfor _, key := range userKeys {var user UseruserStr, _ := zdpgo_redis.String(rdb.Do("GET", key))json.Unmarshal([]byte(userStr), &user)users = append(users, user)}zdpgo_httprouter.ResponseSuccess(w, users)
}func RouterAddUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var user Userzdpgo_httprouter.GetJson(r, &user)id := time.Now().UnixNano()user.Id = id// 新增key := fmt.Sprintf("user/%d", user.Id)zsBytes, _ := json.Marshal(user)value := string(zsBytes)rdb.Do("SET", key, value)// 返回zdpgo_httprouter.ResponseSuccess(w, user)
}func RouterUpdateUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var user Uservar idStr = ps.ByName("id")zdpgo_httprouter.GetJson(r, &user)// 查询key := fmt.Sprintf("user/%s", idStr)userJson, _ := zdpgo_redis.String(rdb.Do("GET", key))// 解析var dbUser Userjson.Unmarshal([]byte(userJson), &dbUser)// 修改dbUser.Name = user.NamedbUser.Age = user.Age// 重新存储jsonBytes, _ := json.Marshal(dbUser)rdb.Do("SET", key, string(jsonBytes))// 返回zdpgo_httprouter.ResponseSuccess(w, dbUser)
}func RouterDeleteUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var idStr = ps.ByName("id")// 查询key := fmt.Sprintf("user/%s", idStr)rdb.Do("DEL", key)// 返回zdpgo_httprouter.ResponseSuccess(w, nil)
}func main() {InitRedis()router := zdpgo_httprouter.New()router.POST("/user", RouterAddUser)router.GET("/user", RouterGetUser)router.PUT("/user/:id", RouterUpdateUser)router.DELETE("/user/:id", RouterDeleteUser)server := &http.Server{Addr: "0.0.0.0:8888",Handler: router,ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,}server.ListenAndServe()
}
package mainimport ("fmt""github.com/zhangdapeng520/zdpgo_httprouter""io"
)func main() {targetUrl := "http://localhost:8888/user/53"data := map[string]interface{}{}resp, err := zdpgo_httprouter.SendJson("DELETE", targetUrl, data)if err != nil {fmt.Println(err)return}body := resp.BodybodyBytes, err := io.ReadAll(body)if err != nil {fmt.Println(err)return}fmt.Println(string(bodyBytes))
}
25 实现根据ID查询用户的接口并进行测试
package mainimport ("encoding/json""fmt""github.com/zhangdapeng520/zdpgo_httprouter""github.com/zhangdapeng520/zdpgo_redis""net/http""time"
)type User struct {Id int64 `json:"id"`Name string `json:"name"`Age int `json:"age"`
}var (pool *zdpgo_redis.Pool
)func InitRedis() {pool = &zdpgo_redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (zdpgo_redis.Conn, error) {return zdpgo_redis.Dial("tcp", "127.0.0.1:6379")},}
}func RouterGetUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()// 获取所有的keyuserKeys, _ := zdpgo_redis.Strings(rdb.Do("KEYS", "user/*"))// 查询var users []Userfor _, key := range userKeys {var user UseruserStr, _ := zdpgo_redis.String(rdb.Do("GET", key))json.Unmarshal([]byte(userStr), &user)users = append(users, user)}zdpgo_httprouter.ResponseSuccess(w, users)
}func RouterAddUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var user Userzdpgo_httprouter.GetJson(r, &user)id := time.Now().UnixNano()user.Id = id// 新增key := fmt.Sprintf("user/%d", user.Id)zsBytes, _ := json.Marshal(user)value := string(zsBytes)rdb.Do("SET", key, value)// 返回zdpgo_httprouter.ResponseSuccess(w, user)
}func RouterUpdateUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var user Uservar idStr = ps.ByName("id")zdpgo_httprouter.GetJson(r, &user)// 查询key := fmt.Sprintf("user/%s", idStr)userJson, _ := zdpgo_redis.String(rdb.Do("GET", key))// 解析var dbUser Userjson.Unmarshal([]byte(userJson), &dbUser)// 修改dbUser.Name = user.NamedbUser.Age = user.Age// 重新存储jsonBytes, _ := json.Marshal(dbUser)rdb.Do("SET", key, string(jsonBytes))// 返回zdpgo_httprouter.ResponseSuccess(w, dbUser)
}func RouterDeleteUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var idStr = ps.ByName("id")// 查询key := fmt.Sprintf("user/%s", idStr)rdb.Do("DEL", key)// 返回zdpgo_httprouter.ResponseSuccess(w, nil)
}func RouterGetUserId(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {rdb := pool.Get()defer rdb.Close()var idStr = ps.ByName("id")// 查询key := fmt.Sprintf("user/%s", idStr)userJson, _ := zdpgo_redis.String(rdb.Do("GET", key))var dbUser Userjson.Unmarshal([]byte(userJson), &dbUser)// 返回zdpgo_httprouter.ResponseSuccess(w, dbUser)
}func main() {InitRedis()router := zdpgo_httprouter.New()router.POST("/user", RouterAddUser)router.GET("/user", RouterGetUser)router.PUT("/user/:id", RouterUpdateUser)router.DELETE("/user/:id", RouterDeleteUser)router.GET("/user/:id", RouterGetUserId)server := &http.Server{Addr: "0.0.0.0:8888",Handler: router,ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,}server.ListenAndServe()
}
package mainimport ("fmt""io""net/http"
)func main() {resp, err := http.Get("http://localhost:8888/user/1")if err != nil {fmt.Println(err)return}body := resp.BodybodyBytes, err := io.ReadAll(body)if err != nil {fmt.Println(err)return}fmt.Println(string(bodyBytes))
}
总结
本套教程主要讲解Go语言操作Redis基础知识,然后还讲解了管道,连接池,事务等高级用户。借助用户管理这个业务为中心,详细讲解了如何使用Go语言加Redis实现用户的增删改查操作,之后有结合httprouter的用法,开发用户管理的增删改查API接口。
通过本套课程,能帮你入门Go语言操作Redis的技术。
如果您需要完整的源码,打赏20元即可。
人生苦短,我用Python,我是您身边的Python私教~
相关文章:

Go+Redis零基础到用户管理系统API实战_20240730 课程笔记
概述 如果您没有Golang的基础,应该学习如下前置课程。 Golang零基础入门Golang面向对象编程Go Web 基础Go语言开发REST API接口_20240728Go语言操作MySQL开发用户管理系统API教程_20240729Redis零基础快速入门_20231227 基础不好的同学每节课的代码最好配合视频进…...

ScreenAgent:基于LVLM的计算机控制智能体
ScreenAgent : A Vision Language Model-driven Computer Control Agent 论文链接: https://arxiv.org/abs/2402.07945https://arxiv.org/abs/2402.07945IJCAI 2024 1.概述 大型语言模型(LLM),诸如ChatGPT与GPT-4,在自然语言处理领域(涵盖生成、理解及对话等任务)展现出…...

谷粒商城实战笔记-129-商城业务-商品上架-nested数据类型场景
文章目录 扁平化处理扁平化处理导致的检索问题 解决方案:使用 nested 结构 在es的数据类型中有一个nested类型,本讲将重点讨论这个类型。 扁平化处理 PUT my_index/doc/1 {"group" : "fans","user" : [{"first&quo…...

axios请求响应拦截器
目录 axios-拦截器 拦截器的作用 请求拦截器-基本写法: axios请求拦截器-统一设置token 需求: 核心步骤: 关键代码: 响应拦截器-基本写法: axios响应拦截器-统一处理token失效 需求: 核心步骤: 关键代码: axios响应拦截器-数据剥离 需求: 核心步骤: 关键代码: ax…...

Python 中单例模式实现的几种方式
在设计模式中,单例模式是经常被提及和使用的一种模式。它保证一个类只有一个实例,并提供全局访问点。在Python中,有多种实现单例模式的方法。那么,如何选择合适的方法来实现单例模式呢? 单例模式在Python中的几种实现方…...

mysql数据库触发器同步数据
首先检查数据源库是否支持触发器,show ENGINES,如果FEDERATED是NO,表示未开启,如需开启,再mysql配置文件中,添加federated配置到mysqld下面。 一、同服务器不同库触发器同步,这里只举例插入数据…...

Prometheus-v2.45.0+Grafana+邮件告警
目录 普罗米修斯监控架构介绍 Prometheus 监控架构 1. 数据抓取(Scraping) 2. 时序数据库(TSDB) 3. 数据模型 4. PromQL 查询语言 5. 告警(Alerting) 6. Alertmanager 7. 可视化(Visu…...
LeetCode——572. 另一颗树的子树
通过万岁!!! 题目:给你两棵树,然后问subRoot是不是root的子树。也就是root某个节点的所有孩子节点在值和结构上完全与subRoot相同。思路:我的思路比较简单,就是遍历root,遇到root中…...

Spring Boot整合MyBatis-Flex
说明:MyBatis-Flex(官网地址:https://mybatis-flex.com/),是一款数据访问层框架,可实现项目中对数据库的访问,类比MyBatis-Plus。本文介绍,在Spring Boot项目整合MyBatis-Flex。 创…...

重塑未来体验:边缘计算与云原生的完美邂逅
🐇明明跟你说过:个人主页 🏅个人专栏:《未来已来:云原生之旅》🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、云原生的兴起 2、边缘计算的兴起 二、边缘计算基础 …...

浅谈基础数论(c++)
目录 一些常见的符号表示阶乘定理 快速幂模板题代码扩展:矩阵快速幂主要作用 欧拉函数扩展积性函数 欧拉函数求法筛选法求欧拉函数(积性函数) 扩展欧几里得裴蜀定理问题分析代码 问题分析 同余与逆元如何求解逆元扩展欧几里得 例题讲解X-Magi…...

jdk 17新特性 sealed 关键字
通俗理解 sealed 关键字就是给对象继承加了权限控制一样,你必须在我的规则范围内才可以继承我的类 使用 permits 关键字控制允许哪些子类继承 子类必须加以下三个关键字: final 最终继承类(继承到这个类就不允许再往下继承了)n…...

在仪器计量校准中,无尘车间洁净室检测有哪些方法和流程?
仪器计量校准行业内,无尘车间洁净室检测可以说是较为热门的业务,因为其预算高,且检测流程不是太繁琐,很多仪器计量校准机构也是设立相关实验室,专门处理相关仪器的检测。不过虽然许多机构想要涉足该领域,但…...

【跨时代】第四次工业革命彻底来袭!什么是AI+
你有没有一种很割裂的感觉,就是在短视频里,AI已经要改变全世界了 但自己一用,却发现只能和AI聊聊天 画几张图 难道是姿势不对?但具体是哪里不对呢。 作为一个老牌程序员,我前面分享了很多计算机相关内容,总…...
前端性能优化-纲领篇
前端性能优化 本模块将梳理前端性能优化的相关知识点 从浏览器输入 URL 到页面展示发生了什么 完整版请查看[Browser_网络_安全]的部分,这里只是简单的梳理一下 DNS 解析TCP 连接浏览器发出 HTTP 请求服务器处理请求并返回 HTTP 报文浏览器解析渲染页面 性能优…...

深度学习-----------数值稳定性
目录 神经网络的梯度数值稳定性的常见两个问题例子:MLP 梯度爆炸梯度爆炸的问题 梯度消失梯度消失的问题 总结模型初始化和激活函数让训练更加稳定让每层的方差是一个常数 权重初始化正向均值和方差正向均值正向方差 反向均值和方差Xavier初始正向和反向的均值和方差…...
SpringBoot项目接口可以承受的调用次数
一个Spring Boot接口能够承受的调用次数主要取决于几个因素,包括但不限于: 服务器硬件:CPU、内存、硬盘I/O速度以及网络带宽都会直接影响接口的处理能力和并发量。操作系统和JVM配置:操作系统调度策略、JVM的内存分配、垃圾回收机…...

抽象代数精解【8】
文章目录 希尔密码矩阵矩阵基本概念行列式基本概念特殊矩阵关于乘法运算构成群 加解密原理密钥加密函数解密函数 Z 26 上的运算( Z 256 与此类似) Z_{26}上的运算(Z_{256}与此类似) Z26上的运算(Z256与此类似&…...

数据结构与算法 - 二叉树
1. 概述 二叉树是这么一种树状结构:每个节点最多有两个孩子,左孩子和右孩子 完全二叉树:是一种二叉树结构,除了最后一层以外,每一层都必须填满,填充时要遵循从左到右 平衡二叉树:是一种二叉树…...
Spring Cloud Gateway如何给一个请求加请求头
在Spring Cloud Gateway中,可以通过编写一个GlobalFilter来给所有请求加请求头,或者通过编写一个SpecificFilter来给特定路径的请求加请求头。 全局过滤器(GlobalFilter)的实现方式如下: Configuration public class…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
「Java基本语法」变量的使用
变量定义 变量是程序中存储数据的容器,用于保存可变的数据值。在Java中,变量必须先声明后使用,声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例:声明与初始化 public class VariableDemo {publi…...