Testing 如何开始测试go例程?

Testing 如何开始测试go例程?,testing,go,Testing,Go,此问题的一个示例是用户创建资源并删除资源。我们将执行该操作并增加(减少)计数器缓存 在测试中,有时存在计数器缓存未被go例程更新的竞争条件 编辑:很抱歉造成混淆,澄清一下:计数器缓存不在内存中,它实际上是数据库中的一个字段。竞争条件不是内存中的变量,实际上是goroutine写入数据库本身的速度可能很慢 我目前在操作后使用1秒睡眠,以确保在测试计数器缓存之前已更新计数器缓存。有没有另一种方法来测试go例程,而不需要在等待go例程完成的情况下进行任意1秒的睡眠 干杯 在测试中,有时存在计数器缓存未

此问题的一个示例是用户创建资源并删除资源。我们将执行该操作并增加(减少)计数器缓存

在测试中,有时存在计数器缓存未被go例程更新的竞争条件


编辑:很抱歉造成混淆,澄清一下:计数器缓存不在内存中,它实际上是数据库中的一个字段。竞争条件不是内存中的变量,实际上是goroutine写入数据库本身的速度可能很慢

我目前在操作后使用1秒睡眠,以确保在测试计数器缓存之前已更新计数器缓存。有没有另一种方法来测试go例程,而不需要在等待go例程完成的情况下进行任意1秒的睡眠

干杯

在测试中,有时存在计数器缓存未被go例程更新的竞争条件。我目前在操作后使用1秒睡眠,以确保在测试计数器缓存之前已更新计数器缓存

哎呀,我不想说,但你做错了。Go具有一流的特性,使并发变得简单!如果你正确使用它们,就不可能有比赛条件

事实上,有一种工具可以。我敢打赌它会抱怨你的节目

一个简单的解决方案:

  • 让主例程创建一个goroutine来跟踪计数器
  • goroutine只需执行一个select并获取一条消息来递增/递减或读取计数器。(如果正在读取,将在通道中传递以返回数字)
  • 创建/删除资源时,通过goroutine计数器的通道向其发送适当的消息
  • 当您想要读取计数器时,发送一条消息进行读取,然后读取返回通道

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

一种解决方案是让您的柜台提供一个频道,该频道会在收到值后立即更新 变化。在围棋中,通常的做法是通过交流结果来同步。比如你的
Couter
可能如下所示:

type Counter struct {
   value int
   ValueChange chan int
}

func (c *Counter) Change(n int) {
    c.value += n
    c.ValueChange <- c.value
}
v := <-c.ValueChange
同时调用
c.Change
不再是问题


有一个。

一点代码示例就好了。我知道你试图摆脱睡眠和种族状况,但我猜不出你的代码是什么样子。试一试,如果你还没有使用频道,听起来你需要的是频道。我支持@miltonb的观点。在代码中引入休眠来“修复”数据争用通常不是正确的解决方案。一旦系统负载过重,超过一秒钟的时间将进入生产,然后睡眠将无法工作。安全构建这些系统的唯一方法是同步。同步通常需要使用通道来发出安全写回的信号。很抱歉混淆了,澄清一下:计数器缓存不在内存中,它实际上是数据库中的一个字段。竞争条件不是内存中的变量,实际上是goroutine写入数据库本身的速度可能很慢@Sidneyisdazhang是的,为此您需要同步。为此,有渠道这样的工具,如果必须的话,还有锁。只有在同步的情况下,才能保证代码以正确的顺序执行。数据位于何处并不重要,重要的是您获取数据的方式。如果您需要在写入结果后读取结果,则无法在不同的goroutine中进行写入和读取。