草庐IT

GO - 代码在函数返回后停止执行

coder 2024-07-06 原文

所以,我正在尝试构建一个 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/

有关GO - 代码在函数返回后停止执行的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用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

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在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. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  5. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  6. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程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

  7. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  8. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  9. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  10. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

随机推荐