Golang正则表达式使用及简单示例

Golang正则表达式使用及简单示例

我发现很多从写脚本转过来写Go代码的开发者都会对Go的正则表达式 (Regular Expression) 功能有微词。普遍觉得其灵活性和完善度都不太给力。其实两个都是有原因的。灵活性其实主要是对Go regexp包的设计哲学不理解。完善度则主要是因为regexp包承诺match的时间与输入长度成线性关系,因此有些表达式就无法支持了, 比如 (?!re)

The regexp implementation provided by this package is guaranteed to run in time linear in the size of the input.

所以,本质上这不是一个「够不够完善」的问题,而是「技术实现决定了它支持程度就是这样」。更多讨论可以关注这里

Go的正则表达式采用RE2语法,详细语法及支持情况可以参阅[这里]。

regex包的设计原则

regexp包的方法命名规则如下:

Find(All)?(String)?(Submatch)?(Index)?

  1. 包含All的方法捕获所有match, 返回值是一个slice. 同时一般会提供一个参数n作为最大匹配次数。
  2. 包含String的方法对string类型进行匹配,反之对[]byte进行匹配。
  3. 包含Submatch的方法返回所有子匹配,返回值是一个slice. 位置0是对应整个正则表达式匹配结果,位置n(n>0)是第n个子表达式(group) 匹配结果。
  4. 包含Index的方法返回匹配的位置。例如,返回loc []int, 则与之对应的匹配字符为src[loc[0]:loc[1]].

匹配Unicode字符

Unicode character class (one-letter name): \pN
Unicode character class: \p{Greek}

含参数

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