jjzjj

go - 停止循环的代码不起作用

coder 2023-07-02 原文

我正在尝试在 Go 中实现循环停止。 我现在拥有的代码的灵感来自这里: how to kill goroutine

但是,我无法让我的代码按预期运行。我的代码来自复杂代码库的简化版本是这样的:

package main

import (
    "fmt"
    "time"
)

var quit chan struct{}

var send chan int

func quitroutine() {
    for {
        select {
        case cnt := <-send:
            fmt.Println(cnt)
            if cnt == 5 {
                quit <- struct{}{}
            }
        }
    }
}

func runLoop() {
    cnt := 0
    for {
        select {
        case <-quit:
            fmt.Println("quit!")
        default:
            fmt.Println("default")
        }
        fmt.Println("inloop")
        time.Sleep(1 * time.Second)
        cnt++
        send <- cnt
    }
}

func main() {
    quit = make(chan struct{})
    send = make(chan int)
    go quitroutine()
    runLoop()
    fmt.Println("terminated")
}

此代码崩溃:

default
inloop
5
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.runLoop()
    /tmp/t.go:37 +0x1a6
main.main()
    /tmp/t.go:45 +0xa4

goroutine 5 [chan send]:
main.quitroutine()
    /tmp/t.go:18 +0x10e
created by main.main
    /tmp/t.go:44 +0x9f
exit status 2

问题:

  1. 为什么在 cnt 为 5 后它会崩溃? quitroutine 仅在 cnt == 5 时写入 quit channel ,但不会自行终止。当 runLoop 时,如果它在 quit channel 上接收到,应该只打印“quit!” (它不会),但不会自行终止。

  2. 为什么我没有得到“退出!”输出?我什至可以获得 quit channel 吗?

  3. 这需要如何正确实现

最佳答案

正如 Adrian 所说,您的一个 goroutine 正在尝试发送 quit ,而另一个试图发送 send .回答您的问题:

  1. cnt == 5 quitroutine开始尝试发送 quit .因为quit <- struct{}{}不是 select在这种情况下,goroutine 将阻塞直到另一个尝试从 quit 读取.另一个 goroutine 同样被困在试图做 send <- cnt 的过程中。 (当 cnt = 6 时)。

  2. 你永远不会得到“退出!”输出是因为那个 goroutine 被卡住了试图做 send <-cnt .

  3. 我看到的最简单的解决方案是调整 runLoop()这样 send <- cntselect中的一个案例.

我会改变 runLoop()看起来像这样:

func runLoop() {
    cnt := 0
    for {
        select {
        case <-quit:
            fmt.Println("quit!")
        case send <- cnt: // moved stuff here
            fmt.Println("inloop")
            time.Sleep(1 * time.Second)
            cnt++
        default:
            fmt.Println("default")
        }
        // stuff used to be here
    }
}

这给了我输出(直到我终止程序):

default
inloop
0
inloop
1
inloop
2
inloop
3
inloop
4
inloop
5
quit!
default
inloop
6
inloop
7

这似乎主要是您所追求的。

我还想指出 select阻止 quitroutine()是不必要的,因为它只有一种情况。清理它可能会更清楚地表明 goroutine 在尝试发送时卡住了,并且永远不会从 send 中获取输入。 channel 。

关于go - 停止循环的代码不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46103456/

有关go - 停止循环的代码不起作用的更多相关文章

  1. ruby - 树顶语法无限循环 - 2

    我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. 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​​

  4. 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

  5. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  6. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

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

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

  8. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  9. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  10. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

随机推荐