将顺序测试分为4个例程,如果其中一个失败,则终止所有测试

问题描述:

我刚开始阅读golang,请随身携带。 假设我有一个简单的循环,它可以执行像这样的顺序测试。将顺序测试分为4个例程,如果其中一个失败,则终止所有测试

for f := 1; f <= 1000; f++ { 
      if doTest(f) { 
       break 
      } 
    } 

我循环遍历数字范围并对每个数字进行测试。如果测试失败的一个号码,我打破并退出主线程。够简单。

现在,如何在四个或几个例行程序中正确提供测试编号。基本上,我想以4个批次(或任何数量的例程)测试1到1000之间的数字。 我是否创建4个例程从一个通道中读取数据并将数字顺序送入此通道?或者我可以制作4个单独的频道?

还有一个问题。如果其中一个程序未通过测试,我如何停止所有4个程序?我一直在阅读频道上的一些文章,但我不能把这些文章放在一起。

谢谢。

+1

你说的是测试,你不是指我猜测的单元测试吗?我无法想象一个正确的单元测试需要你的手动去例行调度 – blang

+0

不,当然,我不是指单元测试..我的意思是任何返回bool的工作..对不起,如果我说错了。应该可能重写标题。假设我想测试一下这个数字是一个素数还是可以被其他数字整除。真的没关系。 –

+0

看看我的回答,这是我猜你最喜欢的场景。但还有其他选择,但不是干净的IMO。 – blang

您可以创建一个生产者/消费者系统:https://play.golang.org/p/rks0gB3aDb

func main() { 
    ch := make(chan int) 
    clients := 4 
    // make it buffered, so all clients can fail without hanging 
    notifyCh := make(chan struct{}, clients) 
    go produce(100, ch, notifyCh) 

    var wg sync.WaitGroup 
    wg.Add(clients) 
    for i := 0; i < clients; i++ { 
     go func() { 
      consumer(ch, notifyCh) 
      wg.Done() 
     }() 
    } 
    wg.Wait() 

} 

func consumer(in chan int, notifyCh chan struct{}) { 
    fmt.Printf("Start consumer\n") 
    for i := range in { 
     <-time.After(100 * time.Millisecond) 
     if i == 42 { 
      fmt.Printf("%d fails\n", i) 
      notifyCh <- struct{}{} 
      return 
     } else { 
      fmt.Printf("%d\n", i) 
     } 

    } 
    fmt.Printf("Consumer stopped working\n") 
} 

func produce(N int, out chan int, notifyCh chan struct{}) { 
    for i := 0; i < N; i++ { 
     select { 
     case out <- i: 
     case <-notifyCh: 
      close(out) 
      return 
     } 
    } 
    close(out) 
} 

生产者推从0到99数字的渠道,消费者消费直到通道被关闭。主要我们创建4个客户端,并将它们添加到一个waitgroup中,以可靠地检查每个goroutine是否返回。 每个消费者都可以在notifyCh上发信号,生产者停止工作,并且不会生成进一步的号码,因此所有消费者都会在当前号码后返回。

还有一个选项可以创建4个例程,等待所有例程返回,开始下一个4个例程。但是这在等待时增加了相当的开销。

既然你提到的质数,这里有一个非常酷的黄金钛硅分子筛:https://golang.org/doc/play/sieve.go

你是否会建立一个共同的通道或通道每个例程取决于你想要什么。

如果你只想在里面放一些数字(或者更一般的请求),你不关心哪个goroutine服务那个,当然比分享一个频道更好。例如,当你想要第一个250请求由goroutine1服务时,当然你不能共享一个频道。

对于渠道是一个很好的做法,用它作为输入或输出。而发件人如何发送简单的东西,他完成了关闭频道。好的文章是https://blog.golang.org/pipelines

什么是没有提到的问题 - 你是否还需要另一个通道(或通道)或任何其他通信原语来获得结果。这里是最有趣的频道比喂食。

应该发送什么信息 - 它应该每doTest后发送,一个布尔值,或者只是知道,当寄托都做(但这种情况下,既不布尔是没有必要只是关闭通道)?

如果您更喜欢第一次失败的程序。比我更喜欢使用缓冲共享通道来提供数字。不要忘记关闭它,当所有的数字将被喂养。

而另一缓冲瓒让主线程知道,测试完成。它可以是频道,那里你只放置数字,测试失败,或者如果你还想要一个肯定的结果 - 包含数字和结果的结构通道,或从doTest返回的任何其他信息。

有关渠道非常好的文章也http://dave.cheney.net/2014/03/19/channel-axioms

每四位够程可报告故障的(通过发送错误和关闭渠道)。但是,当所有数字通过并且饲料渠道关闭时,问题就变成了应该做的事情。关于这也是不错的文章http://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/

+0

是的,做测试返回布尔值。如果四个程序中的任何一个未通过测试,则所有四个程序都应该终止。这个想法很简单,我只是想知道如何实现它。我想连续为每个数字运行一些工作。范围可以是[1..1000]或[1..1000000000]鉴于范围可能很长,我想在四个并行线程中拆分测试,并以四个块为单位测试数字。问题是如何在go中构造这个以及如果其中一个例程未能通过测试,如何终止所有线程。感谢文章,我会读一读 –