Golang反射的使用的正确姿势

Golang反射的使用的正确姿势

Go本身不支持模板,因此在以往需要使用模板的场景下往往就需要使用反射(reflect). 反射使用多了以后会容易上瘾,有些人甚至会形成一种莫名其妙的鄙视链。文人相轻,看来在需要动手指的领域历来如此:) 。反射有两个问题,在使用前需要三思:

  1. 大量的使用反射会损失一定性能
  2. Clear is better than clever. Reflection is never clear.

Go的类型设计上有一些基本原则,理解这些基本原则会有助于你理解反射的本质:

  1. 变量包括 <type, value> 两部分。理解这一点你就知道为什么nil != nil了。
  2. type包括 static typeconcrete type. 简单来说 static type是你在编码是看见的类型,concrete type是runtime系统看见的类型。
  3. 类型断言能否成功,取决于变量的concrete type,而不是static type. 因此,一个 reader变量如果它的concrete type也实现了write方法的话,它也可以被类型断言为writer.
  4. Go中的反射依靠interface{}作为桥梁,因此遵循原则3. 例如,反射包.Kind方法返回的是concrete type, 而不是static type.

Talk is cheap, show some code:

Golang中使用gorm小结

Golang中使用gorm小结

项目中使用orm的好处很多:

  1. 防止直接拼接sql语句引入sql注入漏洞
  2. 方便对modle进行统一管理
  3. 专注业务,加速开发

坏处也是显而易见的:

  1. 开发者与最终的sql语句隔了一层orm,因此可能会不慎引入烂sql
  2. 依赖于orm的成熟度,无法进行一些「复杂」的查询。当然,复杂的查询一大半都是应该从设计上规避的

留意不合法的时间值

MySQL的DATE/DATATIME类型可以对应Golang的time.Time。但是,如果DATE/DATATIME不慎插入了一个无效值,例如2016-00-00 00:00:00, 那么这条记录是无法查询出来的。会返回gorm.RecordNotFound类型错误。零值0000-00-00 00:00:00是有效值,不影响正常查询。

留意tagsql:"default:null"

gorm对各种tag的支持非常完善。但是有些行为跟直觉不太一致,需要注意。当对某字段设置tagsql:"default:null"时,你想通过update设置该字段为null就不可能了,只能通过raw sql。这是gorm设计的取向问题。

如何通过gorm设置字段为null

字段允许为null值肯定是设计存在问题。但是,往往前人埋下的坑需要你去填。gorm作者给出了两种方法,以string为例:

  1. 在golang中,声明该字段为*string
  2. 使用sql.NullString类型

推荐使用后者。

留意连接串中的loc

例如通过如下连接串打开mysql连接:

parseTime=true&loc=Local说明会解析时间,时区是机器的local时区。机器之间的时区可能不一致会设置有问题,这导致从相同库的不同实例查询出来的结果可能解析以后就不一样。因此推荐将loc统一设置为一个时区,如parseTime=true&loc=America%2FChicago

golang中的错误处理模式

年前拜读了Rob Pike的Errors are values,不禁感叹——原来错误可以这样处理。这里简单做一个笔记。

模式1:闭包记录异常

这种方式适用于多次相同类型调用的错误处理。缺点就是,每个类似的地方都需要引入一个闭包函数,显得冗余重复。

模式2:组合error struct

代码比第一种方式更加干净。但是与第一种方式有一样的问题,就是无法具体的知道是在哪个位置发生的错误以及错误的具体信息。

模式3:error转化为panic

来自知乎唐生的回答:

这种方式的通用性较好。但是把error主动转化为panic会导致goroutine的stack unwind。这会带来一定的系统开销,甚至是系统性能抖动。

参考: