百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

Golang 入门系列(七)整合Redis详解, 实战!

wptr33 2024-12-31 15:03 28 浏览

前面讲介绍了Go 语言的基础入门及Golang的语法结构。同时也介绍Golang的接口及协程等内容。感兴趣的朋友可以先看看之前的文章。这些都是Golang的基础内容,必须熟练掌握。

接下来我会介绍golang 的实战,实际开发过程中怎么用golang写实际的功能需求,怎么集成其他框架。

今天跟大家分享的是如何在golang中使用redis数据缓存。

安装

1. Redis 的安装很简单,我这里测试直接用的是windows 的版本。如何安装就不细说了。想了解的可以看之前的文章:https://www.cnblogs.com/zhangweizhong/category/771056.html

2. golang 客户端,用的是 go-redis,

  1、go get github.com/go-redis

2、接着在代码中导入此包即可:

  import "github.com/go-redis/redis"

Redis连接

通过 redis.NewClient 函数即可创建一个 redis 客户端, 这个方法接收一个 redis.Options 对象参数, 通过这个参数, 我们可以配置 redis 相关的属性, 例如 redis 服务器地址, 数据库名, 数据库密码等。

// 创建 redis 客户端
func GetRedisClient() *Client {
    redisdb := NewClient(&Options{
        Addr:     "127.0.0.1:6379",
        Password: "",           // no password set
        DB:       0,                 // use default DB
    })

    pong, err := redisdb.Ping().Result()
    if err != nil {
        fmt.Println(pong, err)
    }
    return redisdb
}

通过 cient.Ping() 来检查是否成功连接到了 redis 服务器

基本使用

Redis支持诸如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、带范围查询的排序集合(sorted sets)、位图(bitmaps)、hyperloglogs、带半径查询和流的地理空间索引等数据结构(geospatial indexes)。其实主要常用的就是:字符串、列表、哈希和集合这四种数据结构。

1、String 操作

  Set(key, value):给数据库中名称为key的string赋予值valueget(key):返回数据库中名称为key的string的value

  GetSet(key, value):给名称为key的string赋予上一次的value

  MGet(key1, key2,…, key N):返回库中多个string的value

  SetNX(key, value):添加string,名称为key,值为value

  SetXX(key, time, value):向库中添加string,设定过期时间time

  MSet(key N, value N):批量设置多个string的值

  MSetNX(key N, value N):如果所有名称为key i的string都不存在

  Incr(key):名称为key的string增1操作

  Incrby(key, integer):名称为key的string增加integer

  Decr(key):名称为key的string减1操作

  Decrby(key, integer):名称为key的string减少integer

  Append(key, value):名称为key的string的值附加valuesubstr(key, start, end):返回名称为key的string的value的子串

示例代码如下:

func StringDemo() {
    fmt.Println("-----------------------welcome to StringDemo-----------------------")
    redisClient:=GetRedisClient()
    if redisClient ==nil{
        fmt.Errorf("StringDemo redisClient is nil")
        return
    }

    name := "张三"
    key :="name:zhangsan"
    redisClient.Set(key , name,1 * time.Second)
    val := redisClient.Get(key)
    if val == nil {
        fmt.Errorf("StringDemo get error")
    }
    fmt.Println("name", val)
}

2、List 操作

  RPush(key, value):在名称为key的list尾添加一个值为value的元素

  LPush(key, value):在名称为key的list头添加一个值为value的 元素

  LLen(key):返回名称为key的list的长度

  LRange(key, start, end):返回名称为key的list中start至end之间的元素

  LTrim(key, start, end):截取名称为key的list

  LIndex(key, index):返回名称为key的list中index位置的元素

  LSet(key, index, value):给名称为key的list中index位置的元素赋值

  LRem(key, count, value):删除count个key的list中值为value的元素

  LPop(key):返回并删除名称为key的list中的首元素

  RPop(key):返回并删除名称为key的list中的尾元素

  BLPop(key1, key2,… key N, timeout):lpop命令的block版本。

  BRPop(key1, key2,… key N, timeout):rpop的block版本。

  RPopLPush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部

示例代码如下:

func ListDemo(){
    fmt.Println("-----------------------welcome to ListDemo-----------------------")
    redisClient:=GetRedisClient()
    if redisClient == nil {
        fmt.Errorf("ListDemo redisClient is nil")
        return
    }
    articleKey := "article"
    result,err:=redisClient.RPush(articleKey, "a","b","c").Result() //
    if err!=nil {
        fmt.Println(err)
        return
    }
    fmt.Println("result:",result)

    result,err = redisClient.LPush(articleKey, "d").Result() //
    if err!=nil {
        fmt.Println(err)
        return
    }
    fmt.Println("result:",result)

    length, err := redisClient.LLen(articleKey).Result()
    if err != nil {
        fmt.Println("ListDemo LLen is nil")
    }
    fmt.Println("length: ", length) // 长度

    mapOut,err1:=redisClient.LRange(articleKey,0,100).Result()
    if err1!=nil {
        fmt.Println(err1)
        return
    }
    for inx, item := range mapOut {
        fmt.Printf("\n %s:%s", inx, item)
    }
}

3、Hash 操作

  HSet(key, field, value):向名称为key的hash中添加元素field

  HGet(key, field):返回名称为key的hash中field对应的value

  HMget(key, (fields)):返回名称为key的hash中field i对应的value

  HMset(key, (fields)):向名称为key的hash中添加元素field

  HIncrby(key, field, integer):将名称为key的hash中field的value增加integer

  HExists(key, field):名称为key的hash中是否存在键为field的域

  HDel(key, field):删除名称为key的hash中键为field的域

  HLen(key):返回名称为key的hash中元素个数

  HKeys(key):返回名称为key的hash中所有键

  HVals(key):返回名称为key的hash中所有键对应的value

  HGetall(key):返回名称为key的hash中所有的键(field)及其对应的value

示例代码如下:

func HashDemo() {
    fmt.Println("-----------------------welcome to HashDemo-----------------------")
    redisClient := GetRedisClient()
    if redisClient == nil {
        fmt.Errorf("HashDemo redisClient is nil")
        return
    }
    article := Article{18, "测试文章内容22222", "测试文章内容22222测试文章内容22222测试文章内容22222", 10, 0}
    articleKey := "article:18"
 
    redisClient.HMSet(articleKey, ToStringDictionary(&article))
    mapOut := redisClient.HGetAll(articleKey).Val()
    for inx, item := range mapOut {
        fmt.Printf("\n %s:%s", inx, item)
    }
    fmt.Print("\n")
 
    redisClient.HSet(articleKey, "Content", "测试文章内容")
    mapOut = redisClient.HGetAll(articleKey).Val()
    for inx, item := range mapOut {
        fmt.Printf("\n %s:%s", inx, item)
    }
    fmt.Print("\n")
 
    view, err := redisClient.HIncrBy(articleKey, "Views", 1).Result()
    if err != nil {
        fmt.Printf("\n HIncrBy error=%s ", err)
    } else {
        fmt.Printf("\n HIncrBy Views=%d ", view)
    }
    fmt.Print("\n")
 
    mapOut = redisClient.HGetAll(articleKey).Val()
    for inx, item := range mapOut {
        fmt.Printf("\n %s:%s", inx, item)
    }
    fmt.Print("\n")
 
}

连接池

go-redis 已经实现了 redis 的连接池管理, 因此我们不需要自己手动管理 redis 的连接。

默认情况下,连接池大小是10, 可以通过 redis.Options 的 PoolSize 属性, 我们设置了 redis 连接池的大小为5。

func GetRedisClientPool() *Client{
    redisdb := NewClient(&Options{
        Addr: "127.0.0.1:6379",
        Password: "",
        DB: 0,
        PoolSize: 5,})

    pong, err := redisdb.Ping().Result()
    if err != nil {
        fmt.Println(pong, err)
    }
    return redisdb
}

连接池测试方法:

// 连接池测试
func connectPoolTest() {
    fmt.Println("-----------------------welcome to connect Pool Test-----------------------")
    client :=GetRedisClientPool()
    wg := sync.WaitGroup{}
    wg.Add(10)

    for i := 0; i < 10; i++ {
        go func() {
            defer wg.Done()

            for j := 0; j < 1000; j++ {
                client.Set(fmt.Sprintf("name%d", j), fmt.Sprintf("xys%d", j), 0).Err()
                client.Get(fmt.Sprintf("name%d", j)).Result()
            }

            fmt.Printf("PoolStats, TotalConns: %d, IdleConns: %d\n", client.PoolStats().TotalConns, client.PoolStats().IdleConns);
        }()
    }

    wg.Wait()
}

最后

以上已经把Redis 的基本的用法讲完了,go语言使用Redis 还是非常简单的,大家可以自己动手写代码试试。

获取完整的源代码,欢迎关注:章为忠学架构

推荐阅读:

Golang 入门系列(六)理解Go协程Goroutine,这篇就够了!

Golang 入门系列(四)Golang中的interface,一看就明白

Golang 入门系列(三)打好基本功: Golang 语法基础!

SpringBoot入门系列(一)如何快速创建SpringBoot项目

Nginx总结(六)nginx实现负载均衡

相关推荐

一篇文章带你了解PHP的学习使用(php的教程)

ThinkPHP5实战...

在memcached管理php的session(memcached libevent)

PHP的session(会话管理)一般是以文件形式进行,而在多个Web服务器之间进行session管理时memecached会比文件管理方式更加方便。在这里介绍如何使用memcached管理PHP的s...

php传值和传引用的区别(php 传值和传引用)

php传值:在函数范围内,改变变量值得大小,都不会影响到函数外边的变量值。PHP传引用:在函数范围内,对值的任何改变,在函数外部也有所体现,因为传引用传的是内存地址。传值:和copy是一样的。【打个比...

PHP 常量详解教程(php常量和变量)

常量类似变量,但是常量一旦被定义就无法更改或撤销定义。PHP常量常量是单个值的标识符(名称)。在脚本中无法改变该值。有效的常量名以字符或下划线开头(常量名称前面没有$符号)。注释:与变量不同,常...

php自学零基础入门小知识(php新手入门教程)

我们就把PHP入门当成一个苹果吧!一口一口的吃掉他!不啰嗦了!开始了1、嵌入方法:类似ASP的<%,PHP可以是<?php或者是<?,结束符号是?>,当然您也可以自己指定。2、...

PHP 语法详解(php语法大全)

PHP脚本在服务器上执行,然后向浏览器发送回纯HTML结果。基础PHP语法PHP脚本可放置于文档中的任何位置。PHP脚本以<?php开头,以?>结尾:<?php...

PHP笔记(一)PHP基础知识(php必背知识点)

创建PHP程序PHP代码框架<?php>2.文件命名规则...

PHP 8新特性之Attributes(注解),你掌握了吗?

PHP8的Alpha版本,过几天就要发布了,其中包含了不少的新特性,当然我自己认为最重要的还是JIT,这个我从2013年开始参与,中间挫折无数,失败无数后,终于要发布的东东。不过,今天呢,我不打算谈J...

PHP基本语法之标记与注释(php注释规范)

1、标记由于PHP是嵌入式脚本语言,它在实际开发中经常会与HTML内容混在一起,所以为了区分HTML与PHP代码,需要使用标记对PHP代码进行标识。如:<html>...

php注解(PHP注解 性能)

目标了解和使用php注解,如果你已经掌握其他一种具有注解的语言,例如:java、python等,你在本文中只需要了解点语法就行。示例php8以前的版本,注解写在注释里,如果你掌握其他语言的注解,你是不...

数据丢失?别慌!MySQL备份恢复攻略

想象一下,某个晴朗的午后,你正享受着咖啡,突然接到紧急电话:你的网站或APP彻底挂了!系统崩溃,界面全白。虽然心头一紧,但你或许还能安慰自己:系统崩溃只是暂停服务,数据还在,修复修复就好了。然而,如果...

MySQL 日志:undo log、redo log、binlog

今天来和大家分享MySQL的三个日志文件,可以说MySQL的多数特性都是围绕日志文件实现,而其中最重要的有以下三种:...

MySQL三大日志:binlog、redolog、undolog全解析

binlog概述在MySQL数据库中,binlog可是个相当重要的存在,它的全称为binarylog,也就是二进制日志。它就像是数据库的“记忆本”,记录了所有的DDL(数据定义语言)和...

1、MySQL数据库介绍(mysql数据库简单介绍)

1.1数据库的核心定义数据库的本质数据库乃存储数据对象之容器,涵盖如下关键组件:表(Table)...

MySQL 日志双雄:实时监控与历史归档实战优化

MySQL日志双雄:实时监控+历史归档实战用这招让你家日志系统再也不卡不爆炸MySQL十亿级日志处理:从洪峰到归档全攻略手把手教你用MySQL搞定ELK级日志监控在微服务架构大行其道的今天,日志系统早...