布景

在学习 Golang 开发时,因部分场景需引入 Redis 的运用。以下首要叙述对于循序渐进运用 Redis 过程。从简略创立缓存客户端,然后进一步优化封装自界说的缓存客户端。

引入 Redis

先获取 redis 第三方包 go-redis,它支撑衔接哨兵以及集群形式的 Redis

go get -u github.com/go-redis/redis

界说一初始化游戏启动器失败个大局 Redis 客户端 RedisDB,依据 go-redis 供给例子,初始化客户端

package plugins
var RedisDB *redis.Client
func InitRedis() {
     RedisDB = redis.NewClient(&redis.Options{
     Addr: "localhost:6379",
     Password: ""
     DB: 1,
 })
    pong, err := RedisDB.Ping().Result()
    if err != nil {
        fmt.Println(pong, err)
    }
    fmt.Println("redis 衔接成功")
}
// main.go 中运用
package main
func main(){
 plugins.InitRedis()
 plugins.RedisDB.set("key001","Hello World", time.Second * 60)
}

假如这样用在一个自己http代理的开发的小项目里没有什么问题,但假如是某个产品的服务,其还是有许多的优化空间的。

封装 Redis 操作

现有的工具包供给了许多的缓存办法,但我或许不需求太多,且部分的办法或许还会有其他的功用需求加入处理。所以能够基于 go-redis 封装一个仅有自己需求办法的 redis 。

package cache
// 界说 MyRedis 结构体
type MyRedis struct {
    Client *redis.Client
}
var redisClient *MyRedis
// 封装 redis 实例,供给获取
func GetInstance() *MyRedis {
    return redisClient
}
// 运用单例形式进行封装
var once sync.Once
// 创立 redis 客户端,并给封装的Redis的客户端进行初始化
func NewMyRedis() *redis.Client {
    myRedis := redis.NewClient(&redis.Options{
        Addr:     "http://localhost",
        Password: "",
        DB:       1,
    })
    once.Do(func() {
        redisClient.Client = myRedis
    })
    return myRedis
}
// 自界说 Exist 办法
func (mr *MyRedis) Exist(key string) bool {
    if mr.Client.Get(key) != nil {
        return true
    }
    return false
}
// set 办法
func (mr *MyRedis) Set(key string, value interface{}, duration time.Duration) bool {
    result := mr.Client.Set(key, value, duration)
    if result.Err() != nil {
        return false
    }
    return true
}

1、界说一个 MyRedis 的结构体,其含有 redis 客户端 。Myhttp://www.baidu.comRedis 就是基于 go-redis 完成自己的redis 客户端,并给该结构体绑定自有的 redis 操作办法

2、创立 NewMyRedis 函数,用于创立 redis 实例。创立的实例是用于初始化 MyRedis 的,其间运用 sync.Once 进行封装,避免出现并发情况。

3、创立一个 GetInstance 函数缓存文件夹名称,用于获取自界说 MyRedis 实例的

以上过程完成了封装自己的 Redis 操作,运用时需求先初始化磁盘进行建立 redis 衔接完成初始化 redis 的工设计模式作,然后在应用时就能够获取 MyRe设计模式的集体教学活动方案dis的实例,直接进行相关操作。详细的完成如下:

// main.go  运用封装后的 redis
package main
func main(){
    // 项目启动时初始化 redis 
    cache.NewMyRedis()
    pong, err := rclient.Ping().Result()
    if err != nil {
        fmt.Println(pong, err)
    }
    fmt.Println("redis 衔接成功")
}
// 其他 package 中运用
package user
func getUser() {
    result := cache.GetInstance().Exist("user_001")
    if !result {
        fmt.Println("不存在该数据")
    }
}

署理形式封装缓存客户端

http 404需求变更,期望能够支撑多种缓存,比方 Redis 、memcached等等,期望能够支撑多种缓存产品。能够进一步优化运用署理形式进一步增强代码的可扩展性。

实践从简略到运用规划形式封装 Redis

署理形式

署理形设计模式之禅式:经过界说一个署理类来署理详细类的缓存的视频在哪操控和拜访

署理形式构成:

  • 笼统主题类:经过接口或者笼统类界说详细主题方针要完成的办法
  • 详细主题类:完成了笼统主题类工商银行的详细办法,是最终缓存视频在手机哪里找署理类要引证的详设计模式23模式介绍细类
  • 署理类:供给httpwatch对外的署理类工商银行,内部引证详细的类,它能够拜访、操控或扩展真实主题的功用
// 界说缓存接口,供给自界说的 get、set 办法
type ICache interface {
    Set(key string, value interface{}, ttl time.Duration)
    Get(key string) interface{}
}
type CacheRedis struct {
    Client *redis.Client
}
var credis *CacheRedis
func NewCacheRedis() *redis.Client {
    myRedis := redis.NewClient(&redis.Options{
        Addr:     "http://localhost",
        Password: "",
        DB:       1,
    })
    once.Do(func() {
        credis.Client = myRedis
    })
    return myRedis
}
func (credis *CacheRedis) Set(key string, value interface{}, ttl time.Duration) {
    credis.Client.Set(key, value, ttl)
}
func (credis CacheRedis) Get(key string) interface{} {
    return credis.Client.Get(key)
}
type CacheLocal struct {
    Client *redis.Client
}
func (credis *CacheLocal) Set(key string, value interface{}, ttl time.Duration) {
    credis.Client.Set(key, value, ttl)
}
func (credis CacheLocal) Get(key string) interface{} {
    return credis.Client.Get(key)
}
  1. 界说了一个 ICache 接口 ,其间界说了缓存客户端需求进行哪些操作

  2. 分别界设计模式的6大原则说了2种详细的缓存类,完成了 ICache 接口。同时也需求供给初始化这2种缓存Clie设计模式的6大原则nt 的函数

  3. 创立一个对外http 500的署理类 CacheClient。其间添加了一个 InitInstance 函数 和 getDriver办法。

    • InihttpwatchtInstance 函数首要用http 500于依据类型进行初始化缓存实例。这儿进行了晋级,和一般的署http代理理形式不同,这儿经过缓存视频合并app类型进行判别进行不同的缓存实例,然后完成依据不同的类型运用不同的缓存实例
    • gethttp://www.baidu.comDriver 办法,经过 getDriver 完成动态署理,署理的过程由该办法来判别运用何种缓存,继而调用其真正的缓存办法。
type CLIENT_TYPE string
const (
    CACHE_REDIS CLIENT_TYPE = "CACHE_REDIS"
    CACHE_LOCAL             = "CACHE_LOCAL"
)
type CacheClient struct {
    ClientType CLIENT_TYPE
    CRedis     *CacheRedis
    CLocal     *CacheLocal
}
var CacheCli *CacheClient
var ccache *CacheRedis
var lcache *CacheLocal
// 初始化缓存 cli 的函数,用于项目程序启动时运用
func InitInstance(clientType CLIENT_TYPE) {
    CacheCli.ClientType = clientType
    switch clientType {
    case CACHE_LOCAL:
        CacheCli.CRedis.Client = NewCacheRedis()
    case CACHE_REDIS:
        CacheCli.CLocal.Client = NewCacheRedis()
    default:
        break
    }
}
func (client *CacheClient) getDriver() ICache {
    if client.CLocal.Client != nil {
        return client.CLocal
    }
    return client.CRedis
}
func (credis *CacheClient) Set(key string, value interface{}, ttl time.Duration) {
    credis.getDriver().Set(key, value, ttl)
}
func (credis *CacheClient) Get(key string) interface{} {
    return credis.getDriver().Get(key)
}

以上是运https和http的区别用过程中界说的源代码,详细的在main 函数中运用如下:

在项目启动时初始缓存文件夹名称化缓存 Cli,然后就能够运用结构体为 CacheClient 的署理缓存 Cli:CacheCli 进行redis 操作。

func main(){
   // 依据缓存类型初始化缓存 Cli
  cache.InitInstance(cache.CACHE_REDIS)
  // 运用结构体为 CacheClient 的署理缓存 Cli:CacheCli 进行redis 操作
  data := cache.CacheCli.Get("hhh001_11") 
  fmt.Println(data)
}

署理形式的优势:

  • 首要起到一个中介作用,对外屏蔽详细方针方针的完成。
  • 在必定程度上降低了系统的耦合度,详细方针方针内部办法事务变更不影响调用者
  • 添加程序的可扩展性,当需求扩展多个方针方针时能够添加方针类型,添加方针类型所对应的方针的完成,然后署理类只需求在初始化时经过不同类型初始化不同的方针方针。

扩展考虑

1、考虑点:署理形式是否还能够继续优化?

应该还有需求优化的点。暂未想到,欢迎留言点拨。

2、考虑点:当作一种规划模版,运用于其他的中间件,比方数据库,音讯行列,存储服务?

署理形式这种方法适用初始化电脑的后果于多个方针方针的,然后依据不同需求动态切换不同的方针方针。比方多种数据库的时分,能够经过 config 装备数据库类型,动态的初始化对应的数据库。也能够代码上操控不同的类型动态切换不同的数据源。http 302

3、考虑点:其他方法完成?

暂时没有想到其他的方法封装 Redis 。假如你有很好的建初始化电脑的后果议能够留言,让公积金我学习学习。

参考资料:

  • [瞎写个 golang 脚本]03-衔接 DB 和 redis –
  • 规划形式之笼统工厂形式:「替换多种缓存http://192.168.1.1登录,署理笼统场景」
  • 署理形式(署理规划形式)详解

我正在参加技术社区创作者签约方案招募活动,点击链接报名投稿。