所以,我正在尝试构建一个 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
}
我在 Listen
的最后一行尝试了使用和不使用 return作为对@SimoEndre 的回应,我已将 main 方法排除在代码示例之外,但既然你提到了它,这就是将 g.Messege{} 从 Messeges channel 中取出的函数。
注意: MessageHandler() 在其自己的 go 例程中运行。
func MessageHandler() {
for msg := range Messages {
for _, disc := range LivingDiscussions {
if disc.DiscussionID.UDID == msg.UDID {
go disc.Push(msg)
break
}
}
}
}
最佳答案
查看 Listen 函数,您会注意到它有一个 Messages channel ,该 channel 接收 Message{} 结构,但在main goroutine 它不会被输出。请记住,goroutine 是双向通信 channel ,这意味着如果 channel 确实接收到输入值,则它必须具有输出值, channel 才不会阻塞。
因此您需要创建一个与 Message{} 结构类型相同的 channel
message := make(chan Message{})
然后在 Join 函数中,您必须弹出推送到 channel 的值:
func Join(ws *websocket.Conn) {
...
<-message
}
新输入后更新:
迭代来自 channel 的值是不够的,您需要在 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 方法是如何实现的,但是如果您的想法是将接收到的 channel 值推送到堆栈,您必须修改您的代码以发送回数组的 channel 值。在上面的代码片段中,我只是想强调将值推回 channel 很重要。
关于GO - 代码在函数返回后停止执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37114221/
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru