ash*_*lal 1 channel go goroutine
我正在尝试实现这里建议的观察者模式; Go语言中的观察者模式
(上面列出的代码不编译且不完整).这里是一个完整的代码编译,但我得到死锁错误.
package main
import (
"fmt"
)
type Publisher struct{
listeners []chan int
}
type Subscriber struct{
Channel chan int
Name string
}
func (p *Publisher) Sub(c chan int){
p.listeners = append(p.listeners, c)
}
func (p *Publisher) Pub(m int, quit chan int){
for _, c := range p.listeners{
c <- m
}
quit <- 0
}
func (s *Subscriber) ListenOnChannel(){
data := <-s.Channel
fmt.Printf("Name: %v; Data: %v\n", s.Name, data)
}
func main() {
quit := make(chan int)
p := &Publisher{}
subscribers := []*Subscriber{&Subscriber{Channel: make(chan int), Name: "1"}, &Subscriber{Channel: make(chan int), Name: "2"}, &Subscriber{Channel: make(chan int), Name: "3"}}
for _, v := range subscribers{
p.Sub(v.Channel)
go v.ListenOnChannel()
}
p.Pub(2, quit)
<-quit
}
Run Code Online (Sandbox Code Playgroud)
此外,如果我完全摆脱'退出',我没有错误,但它只打印第一个记录.
问题是你正在发送退出接收的同一个goroutine quit.
quit具有为0的缓冲器大小,这意味着为了进行,必须有在一侧上的发送器,而在另一接收机在同一时间.你正在发送,但没有人在另一端,所以你永远等待.在这种特殊情况下,Go运行时能够检测到问题和恐慌.
删除退出时仅打印第一个值的原因是您的主要goroutine在剩余的两个能够打印之前退出.
不要不只是增加通道的缓冲区大小摆脱这样的问题.它可以提供帮助(虽然在这种情况下它没有),但它只能解决问题,并没有真正解决根本原因.增加通道的缓冲区大小绝对是一种优化.事实上,通常在没有缓冲区的情况下开发更好,因为它使并发问题更加明显.
有两种方法可以解决问题:
quit,但在每个goroutine内部发送0 ListenOnChannel.在进行之前main,请确保从每个goroutine收到一个值.(在这种情况下,您将等待三个值.)| 归档时间: |
|
| 查看次数: |
3231 次 |
| 最近记录: |