上一篇发布的文章应该也算是总结,也是工作中遇到的问题。现在入职新公司半个多月,.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和多条件查询
有疑问加站长微信联系(非本文作者)