美文网首页每周总结
Golang实践总结(一) -- interface和类型断言、

Golang实践总结(一) -- interface和类型断言、

作者: 魔改谢馒头 | 来源:发表于2018-09-21 18:16 被阅读0次

    上一篇发布的文章应该也算是总结,也是工作中遇到的问题。现在入职新公司半个多月,.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和类型断言、

        本文链接:https://www.haomeiwen.com/subject/jslznftx.html