Golang实践总结(一) -- interface和类型断言、Redis和多条件查询

上一篇发布的文章应该也算是总结,也是工作中遇到的问题。现在入职新公司半个多月,.net的脑子差不多已经换成了golang。目前第一个小项目已经提测,写项目的过程中也遇到了一些小问题,在周末快下班的时候做一些总结,消化和拓展一下涉及到的知识点。

interface和类型断言

我们都知道的一点是golang并不支持泛型,但在golang中可以使用interface{}来代替泛型的功能。
在开始自己学习的时候也看到过这个知识点,有大致了解过接口可以通过泛型接收任意类型的变量,然后再在方法里用反射去赋值或者解析。
但是具体使用上会遇到很多小坑,我贴一些代码,举几个例子

func (this *RedisManager) GetValue(redisConn redis.Conn, key string, object interface{}) error {

    result, err := redis.Bytes(redisConn.Do("GET", key))

    if err != nil {
        return err
    }

    err = json.Unmarshal(result, object)

    if err != nil {

        return errors.New(fmt.Sprintf("REDIS-->JSON解码错误: %s %s", reflect.TypeOf(object), string(result)))
    }

    return nil
}

对于golang传参有了解的同学就能明白这里需要传入一个结构体指针,不能传值类型的参数。因为值类型是一个拷贝,方法内并不能改动方法外的原参数。
那么我们调用函数就应该写成这个样子

var result []*Item
err := Redismgr.GetValue(key, &result)
if err != nil {
...
}

然后我遇到的问题就是,我把这部分需要加工的重复代码又提到了一个新的方法里

func SelectFromRedis(.......,result interface{}) interface{}{
  ....
  err:=Redismgr.GetValue(key, result)
  ....
  return result
}

var result []*Item
result = SelectFromRedis(.....,&result)

好的我们来看一下,上面代码最后一行有个错误。
cannot use SelectFromRedis(.....,&result)(type interface{}) as type []*Item in assignment: need type assertion
IDE会提示你,虽然所有类型都继承了interface,但你不能直接用interface直接当成目标类型来用,你需要写断言。

可以,那按他的提示改一下

result = SelectFromRedis(.....,&result).([]*Item)

这时候IDE也不报错,满心以为程序好使了,但是运行起来以后疯狂报错。
查了半天,打了半天的log,最后发现,因为传入的是&result,传入到SelectFromRedis时的类型已经变成了*[]*Item类型,所以再用[]*Item去断言就会报错了。

对于这种问题有一个很简单的方法就是,如果你并不确定需要断言什么类型,只要把变量的类型打印出来自己看一下再写就好了

fmt.Printf("result type is :%T",result)

Redis和多条件查询

页面是一个多条件筛选还附带日期的一个表格,还有一个图标,后台涉及大量的判断和数据的SUM,GROUP BY,COUNT,SORT操作。平时一次查询大概需要2秒钟,再加上翻页和sort的频繁请求,会对mysql造成不小压力,而且用户体验也很不好。那么这种时候就需要redis去缓存数据,增加效率。

在设计存储结构的时候持久拿不定注意。因为筛选条件太多,需要存条件再存值的话,觉得用ZSET也好,用LIST也可以。想了半天也没有一个很好的办法,最后还是征求了一下大佬的意见。

大佬告诉我说,其实redis在设计的时候,并不需要太过严谨的储存方式,并不需要考虑数据去怎么关联。最核心的思想就是HIT OR MISS,也就是说你需要考虑的只有一个不会重复的键。(听起来像废话)

那么接下来的事情就很简单了,MD5是一个单向,不会重复的加密方式。什么意思呢,就是说我如果输入条件不变的话,最后加密出来的字符串就不会变。而之所以说他单向是因为我除非知道输入条件,是无法通过结果值来反推输入值的。

那么我在存redis的key值时候,完全可以采用 Function Name —— MD5(Request Param)的方式,直接用string类型就可以解决问题了。

你可能感兴趣的:(Golang实践总结(一) -- interface和类型断言、Redis和多条件查询)