亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何高效關閉兩個goroutines?

如何高效關閉兩個goroutines?

Go
GCT1015 2023-05-22 17:07:36
我正在使用兩個并發 goroutine 將 stdin/stdout 從我的終端復制到 net.Conn 目標。出于某種原因,我無法在不出現恐慌錯誤的情況下完全停止這兩個 go 例程(用于嘗試關閉已關閉的連接)。這是我的代碼:func interact(c net.Conn, sessionMap map[int]net.Conn) {    quit := make(chan bool) //the channel to quit    copy := func(r io.ReadCloser, w io.WriteCloser) {        defer func() {            r.Close()            w.Close()            close(quit) //this is how i'm trying to close it        }()        _, err := io.Copy(w, r)        if err != nil {            //        }    }    go func() {        for {            select {            case <-quit:                return            default:                copy(c, os.Stdout)            }        }    }()    go func() {        for {            select {            case <-quit:                return            default:                copy(os.Stdin, c)            }        }    }()}這個錯誤是因為panic: close of closed channel我想終止兩個 go 例程,然后通常繼續執行另一個函數。我究竟做錯了什么?
查看完整描述

2 回答

?
搖曳的薔薇

TA貢獻1793條經驗 獲得超6個贊

你不能close多次調用一個通道,沒有理由調用copyfor 循環,因為它只能運行一次,而且你正在向錯誤的方向復制,寫入標準輸入并從標準輸出讀取。


簡單地詢問如何退出 2 個 goroutines 很簡單,但這不是您在這里需要做的唯一事情。由于io.Copy是阻塞,您不需要額外的同步來確定調用何時完成。這使您可以顯著簡化代碼,從而更容易推理。


func interact(c net.Conn) {

    go func() {

        // You want to close this outside the goroutine if you

        // expect to send data back over a half-closed connection

        defer c.Close()


        // Optionally close stdout here if you need to signal the

        // end of the stream in a pipeline.

        defer os.Stdout.Close()


        _, err := io.Copy(os.Stdout, c)

        if err != nil {

            //

        }

    }()


    _, err := io.Copy(c, os.Stdin)

    if err != nil {

        //

    }

}

另請注意,您可能無法跳出io.Copyfrom stdin,因此您不能指望函數interact返回。在函數體中手動執行io.Copy并檢查每個循環的半關閉連接可能是個好主意,這樣您就可以更快地退出并確保完全關閉net.Conn.


查看完整回答
反對 回復 2023-05-22
?
慕運維8079593

TA貢獻1876條經驗 獲得超5個贊

也可以是這樣的


 func scanReader(quit chan int, r io.Reader) chan string {

          line := make(chan string)

           go func(quit chan int) {

                    defer close(line)

                    scan := bufio.NewScanner(r)

                    for scan.Scan() {

                    select {

                       case <- quit:

                          return

                       default:

                          s := scan.Text()

                          line <- s

                    }

                    }

                }(quit)

               return line

    }


            stdIn := scanReader(quit, os.Stdin) 

            conIn := scanReader(quit, c) 

        for {

            select {

                    case <-quit:

                        return

                    case l <- stdIn:

                        _, e := fmt.Fprintf(c, l)

                        if e != nil {

                           quit <- 1

                           return

                        }

                    case l <- conIn:

                        fmt.Println(l)

                    }

        }


查看完整回答
反對 回復 2023-05-22
  • 2 回答
  • 0 關注
  • 151 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號