为了账号安全,请及时绑定邮箱和手机立即绑定

如何去测试 go 例程?

如何去测试 go 例程?

Go
白板的微信 2021-06-04 15:07:00
此问题的一个示例是当用户创建资源并删除资源时。我们将执行操作并增加(减少)计数器缓存。在测试中,有时会出现竞争条件,即 go 例程尚未更新计数器缓存。编辑:抱歉混淆,澄清一下:计数器缓存不在内存中,它实际上是数据库中的一个字段。竞争条件不是内存中的变量,实际上是 goroutine 写入数据库本身可能很慢!我目前在操作后使用 1 秒睡眠来确保在测试计数器缓存之前更新了计数器缓存。是否有另一种方法来测试 go 例程而无需任意 1 秒睡眠等待 go 例程完成?
查看完整描述

2 回答

?
倚天杖

TA贡献1828条经验 获得超3个赞

在测试中,有时会出现竞争条件,即 go 例程尚未更新计数器缓存。我目前在操作后使用 1 秒睡眠来确保在测试计数器缓存之前更新了计数器缓存。

哎呀,我不想这么说,但你做错了。Go 具有一流的功能,使并发变得容易!如果您正确使用它们,则不可能有竞争条件。

事实上,有一种工具可以为您检测种族。我敢打赌它会抱怨你的程序。

一个简单的解决方案:

  • 让主程序创建一个 goroutine 来跟踪计数器。

  • goroutine 只会做一个选择并获取一条消息来增加/减少或读取计数器。(如果是读取,会传入一个通道返回编号)

  • 当您创建/删除资源时,通过它的通道向 goroutine 计数器发送适当的消息。

  • 当要读取计数器时,发送消息进行读取,然后读取返回通道。

(另一种选择是使用锁。它的性能会更高一点,但编写并确保它是正确的要麻烦得多。)


查看完整回答
反对 回复 2021-06-28
?
慕标琳琳

TA贡献1830条经验 获得超9个赞

一种解决方案是让您的柜台提供一个渠道,该渠道在价值发生变化时立即更新。在 go 中,通过传达结果来同步是常见的做法。例如,您 Couter可能看起来像这样:


type Counter struct {

   value int

   ValueChange chan int

}


func (c *Counter) Change(n int) {

    c.value += n

    c.ValueChange <- c.value

}

每当Change被调用时,新值都会通过通道传递,等待该值的人会解除阻塞并继续执行,因此与计数器同步。使用此代码,您可以监听如下ValueChange更改:


v := <-c.ValueChange

并发调用c.Change不再是问题。


查看完整回答
反对 回复 2021-06-28
  • 2 回答
  • 0 关注
  • 210 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信