为了账号安全,请及时绑定邮箱和手机立即绑定

如何关闭等待 I/O 的 goroutine

如何关闭等待 I/O 的 goroutine

Go
桃花长相依 2021-10-11 10:32:31
我创建了两个 go 例程sender和receiver,sender 将不断从用户(键盘)获取数据并写入流,receiver 将独立地从流中获取值将其打印到屏幕上。两者都使用 goroutine 并发在某个时间点接收器失败并关闭连接并退出接收器 go 例程,但等待用户输入(i/o 操作)的发送器 go 例程不会关闭。这种场景下如何退出所有的goroutine?下面是此场景的示例代码。package mainimport (    "fmt"    "time")var stop bool = falsefunc sender() {    str := ""    for !stop {        fmt.Scanf("%s", &str)        fmt.Println("Entered :", str)    }       fmt.Println("Closing sender goroutine")}func receiver() {    i := 0    for !stop {        i++        if i > 5 {             stop = true        }        time.Sleep(1 * time.Second)    }       fmt.Println("Closing receiver goroutine")}func main() {    go sender()    go receiver()    /* Wait for goroutines to finish */    for !stop {        time.Sleep(1 * time.Millisecond)    }       time.Sleep(1 * time.Second)    panic("Display stack")}上面的代码发送者将在 5 个循环接收者退出接收者程序后等待用户输入。 I expect when receiver close, go routine which waiting on i/o has to be closed.请帮助我解决这个问题。
查看完整描述

2 回答

?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

正如 Dave C 和 JimB 所说,使用通道来协调 goroutine。这是一个可能会有所帮助的示例。


收到用户的5条消息后退出:


package main


import "fmt"


var pipe = make(chan string) //shares text entered by user

var stop = make(chan bool)   //shares stop signal


func listen() {

    for {

        var input string

        fmt.Scan(&input)

        pipe <- input

    }

}


func write() {

    for i := 0; i < 5; i++ {

        var output string

        output = <-pipe

        fmt.Println("Received", output)

    }


    stop <- true

}


func main() {

    go listen()

    go write()


    <-stop

}


查看完整回答
反对 回复 2021-10-11
?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

首先,您的代码有一个围绕stop变量的竞赛。当发生数据竞争时,无法保证您的程序会按照定义的那样运行。使用通道来同步 goroutine。然而,这不是您继续编程的原因。


您的代码在 上阻塞fmt.Scanf,无法检查stop条件。由于无法中断 Stdin 上的读取(发生在 内部fmt.Scanf),因此您需要在Scanf再次调用之前检查停止条件。如果没有更多输入,但您在 Stdin 上有一个待处理的 Read,处理它的最简单方法是让 goroutine 运行。有一些相当复杂的方法可以使用称为“自管道”的技巧来解决这个问题,但通常不值得付出努力,因为 goroutine 很小并且不占用太多资源。


for !stop {

    fmt.Scanf("%s", &str)

    fmt.Println("Entered :", str)

    // use a channel to detect when to exit

    select {

    case <-stop:

        return

    default:

    }

}


查看完整回答
反对 回复 2021-10-11
  • 2 回答
  • 0 关注
  • 225 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信