所以,我正在尝试构建一个websocket服务器。我遇到了这个有趣的错误,我不知道为什么会发生这种错误。
注意: 代码段中的评论仅适用于此帖子。 阅读。
我有这个功能:
func Join(ws *websocket.Conn) {
Log.Connection(ws)
enc := json.NewEncoder(ws)
dec := json.NewDecoder(ws)
var dJ g.DiscussionJoin
var disc g.Discussion
Log.Err(dec.Decode(&dJ), "dec.Decode")
ssD := g.FindDiscussionByID(dJ.DiscussionID)
ssDJ := dJ.Convert(ws)
g.DiscHandle <- &ssDJ
disc = ssD.Convert()
Log.Err(enc.Encode(disc), "enc.Encode")
Log.Activity("Discussion", "Joined", disc.DiscussionID.Subject)
fmt.Println("Listening") //This gets called
g.Listen(dec)
fmt.Println("Stoped Listening") //This DOESN'T get called [IT SHOULD]
ssDJ.SSDiscussion.Leave(ssDJ.SSUserID)
Log.Disconnection(ws)
}
造成这种情况的功能是(在我看来)g.Listen(...):
func Listen(dec *json.Decoder) {
timeLastSent := time.Now().Second()
in := Message{}
for ((timeLastSent + ConnTimeout) % 60) != time.Now().Second() {
if err := dec.Decode(&in); err != nil {
continue
} else if in == Ping {
timeLastSent = time.Now().Second()
continue
}
timeLastSent = time.Now().Second()
Messages <- in
in = Message{}
}
fmt.Println("Client timed out!") //This gets called
return
}
我已经在收听
的最后一行使用和不使用返回进行了尝试作为对@SimoEndre的响应,我将主方法从代码示例中删除了,但是既然你提到了它,那么这就是将g.Messege {}带出Messeges通道的函数。
注意: MessageHandler()在自己的例程中运行。
func MessageHandler() {
for msg := range Messages {
for _, disc := range LivingDiscussions {
if disc.DiscussionID.UDID == msg.UDID {
go disc.Push(msg)
break
}
}
}
}
答案 0 :(得分:2)
查看Listen
函数,您会注意到它有一个Messages
通道,它接收Message{}
结构,但在主goroutine中它不会输出。请记住,goroutine是双向通信通道,这意味着如果通道确实接收到输入值,它必须具有不阻塞通道的输出值。
因此,您需要创建一个与Message{}
message := make(chan Message{})
然后在Join函数中,你必须弹出推送到channel:
的值func Join(ws *websocket.Conn) {
...
<-message
}
新输入后更新:
不足以迭代来自频道的值,您需要在go func()
内执行此操作。
可以使用select
关键字从不同的并发执行goroutine中获取值,该关键字与switch控制语句非常相似,有时也称为通信开关。
go func() {
for msg := range Messages {
for _, disc := range LivingDiscussions {
if disc.DiscussionID.UDID == msg.UDID {
select {
case disc.Push <- msg: // push the channel value to the stack
default :
// default action
}
}
}
}
}()
我不知道您的disc.Push
方法是如何实现的,但如果想要将收到的通道值推送到堆栈,您必须修改代码以回发通道值到阵列。在上面的代码片段中,我只想强调将值重新推入频道非常重要。