Golang中WaitGroup使用的一点坑

Golang中WaitGroup使用的一点坑

Golang 中的 WaitGroup 一直是同步 goroutine 的推荐实践。自己用了两年多也没遇到过什么问题。直到一天午睡后,同事扔过来一段奇怪的代码:

坑1

撇了一眼,觉得没什么问题。然而,它的运行结果是这样:

或这样:

或这样:

一度让我以为手上的 mac 也没睡醒……
这个问题如果理解了 WaitGroup 的设计目的就非常容易 fix 啦。因为 WaitGroup 同步的是 goroutine, 而上面的代码却在 goroutine 中进行 Add(1) 操作。因此,可能在这些 goroutine 还没来得及 Add(1) 已经执行 Wait 操作了。

于是代码改成了这样:

坑2

然而,mac 又睡了过去,而且是睡死了过去:

wg 给拷贝传递到了 goroutine 中,导致只有 Add 操作,其实 Done操作是在 wg 的副本执行的。因此 Wait 就死锁了。于是代码改成了这样:

填坑

至此,午睡终于睡醒了。Sigh…

Golang runtime error with macOS Sierra

Golang runtime error with macOS Sierra

If you are on Golang 1.6 or older, you may meet a panic error when you try to build or test your programme or anything else related with runtime:

fatal error: unexpected signal during runtime execution

There is a post about the issue in golang-nuts: [https://groups.google.com/forum/#!topic/golang-nuts/XaVT6fi1g30]. The bug is fixed in Golang 1.7, so just upgrade to 1.7 and you will be happy.

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}

含参数