jjzjj

go - channel 提前终止

coder 2024-07-13 原文

我正在为每个执行转换的管道制作一系列 go 例程的原型(prototype)。例程在所有数据通过之前终止。

我已经查阅了 Donavan 和 Kernighan 的书并在 Google 上搜索了解决方案。

这是我的代码:

package main

import (
    "fmt"
    "sync"
)

func main() {
    a1 := []string{"apple", "apricot"}

    chan1 := make(chan string)
    chan2 := make(chan string)
    chan3 := make(chan string)

    var wg sync.WaitGroup

    go Pipe1(chan2, chan1, &wg)
    go Pipe2(chan3, chan2, &wg)
    go Pipe3(chan3, &wg)

    func (data []string) {
        defer wg.Done()
        for _, s := range data {
            wg.Add(1)
            chan1 <- s
        }
        go func() {
            wg.Wait()
            close(chan1)
        }()
    }(a1)
}

func Pipe1(out chan<- string, in <-chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    for s := range in {
        wg.Add(1)
        out <- s + "s are"
    }
}
func Pipe2(out chan<- string, in <-chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    for s := range in {
        wg.Add(1)
        out <- s + " good for you"
    }
}
func Pipe3(in <-chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    for s := range in {
        wg.Add(1)
        fmt.Println(s)
    }
}


我的预期输出是:

apples are good for you
apricots are good for you

运行main的结果不一致。有时我会得到两条线。有时我只是得到苹果。有时什么都不输出。

最佳答案

正如 Adrian 已经指出的,您的 WaitGroup.Add 和 WaitGroup.Done 调用不匹配。然而,在这种情况下,“我完成了”信号通常是通过关闭输出 channel 给出的。只有在多个 goroutine 之间共享工作时才需要 WaitGroup(即,多个 goroutine 使用相同的 channel ),而这里不是这种情况。

package main

import (
    "fmt"
)

func main() {
    a1 := []string{"apple", "apricot"}

    chan1 := make(chan string)
    chan2 := make(chan string)
    chan3 := make(chan string)

    go func() {
        for _, s := range a1 {
            chan1 <- s
        }

        close(chan1)
    }()

    go Pipe1(chan2, chan1)
    go Pipe2(chan3, chan2)

    // This range loop terminates when chan3 is closed, which Pipe2 does after
    // chan2 is closed, which Pipe1 does after chan1 is closed, which the
    // anonymous goroutine above does after it sent all values.
    for s := range chan3 {
        fmt.Println(s)
    }
}

func Pipe1(out chan<- string, in <-chan string) {
    for s := range in {
        out <- s + "s are"
    }

    close(out) // let caller know that we're done
}

func Pipe2(out chan<- string, in <-chan string) {
    for s := range in {
        out <- s + " good for you"
    }

    close(out) // let caller know that we're done
}

在 Playground 上试试:https://play.golang.org/p/d2J4APjs_lL

关于go - channel 提前终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57594490/

有关go - channel 提前终止的更多相关文章

  1. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  2. ruby - 提前返回 vs if 在 ruby​​ 代码中 - 2

    我看到有两种写作风格:deffind_nest(animal)returnunlessanimal.bird?GPS.find_nest(animal.do_crazy_stuff)end对比deffind_nest(animal)ifanimal.bird?GPS.find_nest(animal.do_crazy_stuff)endend哪个更正确/更可取/遵循最佳实践?还是无所谓? 最佳答案 根据Rubystyleguide,Preferaguardclausewhenyoucanassertinvaliddata.Aguar

  3. ruby-on-rails - 用于 Ruby 的 vim 中的全局 "Go to definition"? - 2

    自97年以来我一直在使用vi/vim进行各种快速编辑和管理任务,但最近才考虑使用它来替换Netbeans作为我选择的ruby​​编辑器。我发现一件事在Netbeans和Eclipse中非常有用的是Ctrl+Click“转到定义”功能,您可以在其中按住Ctrl键并单击一个类或方法,然后它将带您了解定义。现在,我玩过丰富的ctags和rails.vim,而且很接近,但没有雪茄。这就是我想要的:默认情况下在Netbeans和Eclipse中,您可以在本地rails中按住ctrl并单击本地方法或类项目,但你也可以ctrl+click定义在gems或用Ruby编写的系统库。以Netbeans为例

  4. ruby - 如何在 ruby​​ 中控制(启动/终止)后台进程(服务器应用程序) - 2

    我正在尝试通过ruby​​为集成测试(实际上是规范)设置一个服务器,但不知道如何控制该过程。所以,我要做的是:为我的gem运行一个执行集成规范的rake任务任务需要先启动服务器(我使用webrick),然后运行规范执行规范后,它应该会杀死webrick,这样我就不会留下一些未使用的后台进程webrick不是必需的,但它包含在ruby​​标准库中,因此能够使用它会很棒。希望有人能提供帮助!附言。我在linux上运行,所以让这个适用于windows的工作不是我的主要优先事项(现在)。 最佳答案 标准方法是使用系统函数fork(复制当前进

  5. ruby-on-rails - 如何在 Rails Controller 中调用 channel 方法? - 2

    我有一个订阅用户的ActionCable方法。如果开始新的session,我也想为用户订阅新channel。我想不出在Controller中调用channel方法的正确语法。更新:问题是消息在发送时附加到聊天框,但是当发送第一条消息时,websocket连接尚未建立,因此在用户看来好像消息没有发送(因为它没有被附加)。channel/msgs_channel.rbclassMsgsChannel在我的convosController中,create方法,我尝试了几种方法:convos_controller.rbdefcreate@convo=Convo.create!({sender_

  6. ruby-on-rails - Rails 上的 ruby : How to have multiple submit buttons going to different methods (maybe with with_action? ) - 2

    这个问题在这里已经有了答案:HowdoIcreatemultiplesubmitbuttonsforthesameforminRails?(7个答案)关闭9年前。所以..'save'%>'library'%>然后在我的Controller中:with_actiondo|a|a.savedoenda.librarydoendend问题是只有一个操作被调用...两个submit_tags调用相同的操作...知道为什么吗?或者我如何获得两个按钮以将表单提交给两种不同的方法?

  7. ruby-on-rails - 在 rails 插件之外无法访问 ActionCable channel - 2

    我正在尝试创建一个公开ActionCablechannel的gem,但我无法让它工作。这是我的宝贝#lib/my_channel.rbclassMyChannel然后我将gem添加到我的主要应用程序Gemfile,运行bundleinstall,启动控制台并运行MyChannel。没有屈服和错误,这意味着channel已正确包含。然后我将其添加到我的主应用程序//application.jsvarsocket="ws://localhost:3000/cable";varcable=ActionCable.createConsumer(socket);cable.subscriptio

  8. DiFi: A Go-as-You-Pay Wi-Fi Access System 精读笔记(三) - 2

    IV.SYSTEMIMPLEMENTATIONWeadoptmodulardesignfollowingtheintegrationofblockchain.Itbringsmoreflexibilitybyseparatingtheimplementationofdifferentfunctionalities,sowecouldleveragetheadvantagesoftheblockchain-basedsmartcontractwhilereducingoverhead.Figure3illustrateshowdifferentmodulesareinvolvedintheint

  9. go-templates - 如何根据表达式有条件地在 Go 模板中设置变量,如果不使用 if 语句包装可能会导致错误 - 2

    问题我该如何做这样的事情:{{$use_ssl:=(ne$.Env.CERT_NAME"")}}其中$.Env.CERT_NAME可能为零/未定义。如果它是零,它给出这个错误:at:errorcallingne:invalidtypeforcomparison注意:我无法控制传递给Go模板的对象,因此必须完全在模板本身内解决这个问题。我尝试过的我试图通过首先检查它是否为非空来变通:{{$use_ssl:=(($.Env.CERT_NAME)&&(ne$.Env.CERT_NAME""))}}但它给出了这个错误:unexpected"&"inoperand所以我切换到这个,这在语法上是允

  10. Go time与string的相爱相杀 - 2

    time包与string包可以说是在Go语言的开发中常用的两个包实际开发过程中(例如web开发)经常会遇到time类型与string类型的交互,计算比较等场景首先来了解GO语言里非常浪漫的一个点,即2006-01-0215:04:05,GO语言诞生的时间,通常用来做时间的格式化time转stringt:=time.Now()//当前时间timeLayoutStr:="2006-01-0215:04:05"t.Format(timeLayoutStr)//返回值为string,可以用一个值来接收它上述例子中,将time类型t转换为string类型,并格式化为年-月-日时-分-秒,这里的格式化是可

随机推荐