是的,它很复杂,但是有一些经验法则可以使事情变得简单得多。
- 宁愿使用 传递给go-routine 的通道的形式参数, 而不是访问全局范围内的通道。您可以通过这种方式获得更多的编译器检查,以及更好的模块化。
- 避免在特定的例行程序 (包括“主要” 程序)的同一通道上进行读取和写入 。否则,死锁风险更大。
这是应用这两个准则的程序的替代版本。此案例演示了频道上的许多作家和一位读者:
c := make(chan string)for i := 1; i <= 5; i++ { go func(i int, co chan<- string) { for j := 1; j <= 5; j++ { co <- fmt.Sprintf("hi from %d.%d", i, j) } }(i, c)}for i := 1; i <= 25; i++ { fmt.Println(<-c)}
http://play.golang.org/p/quQn7xePLw
它创建五个go例程写入单个通道,每个例程写入五次。主例程会读取所有25条消息-您可能会注意到它们出现的顺序通常不是顺序的(即,并发很明显)。
此示例演示了Go频道的功能:可能有多个作者共享一个频道;Go将自动插入邮件。
同样适用于一个频道上的一位作者和多个读者,如此处的第二个示例所示:
c := make(chan int)var w sync.WaitGroupw.Add(5)for i := 1; i <= 5; i++ { go func(i int, ci <-chan int) { j := 1 for v := range ci { time.Sleep(time.Millisecond) fmt.Printf("%d.%d got %dn", i, j, v) j += 1 } w.Done() }(i, c)}for i := 1; i <= 25; i++ { c <- i}close(c)w.Wait()
此第二个例子包括施加在主够程等待,否则退出及时并引起其他五个够程要提前终止_(由于[ olov]此校正)_。
在两个示例中,都不需要缓冲。通常,将缓冲仅视为性能增强器是一个很好的原则。如果你的程序不会死锁 没有 缓冲区,也不会发生死锁 与 缓冲区是(但反之
并不 总是正确的)。因此,作为 另一条经验法则,开始时不要缓冲,然后根据需要稍后添加 。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)