想要使用通道从 os.Stdin 写入到 os.Stdout

Want to write from os.Stdin to os.Stdout using channels

/* Want to write from os.Stdin to os.Stdout(fmt.Println() in below code) using channels*/
package main
import (
    "fmt"
    "io"
    "os"
    "bufio"
)

type message []byte
/* Function to run the groutine to run for stdin read */
func read (r io.Reader) <-chan message{
    lines := make (chan message)
    go func() {
        defer close(lines)
        scan := bufio.NewScanner(r)
        for scan.Scan() {
            lines <- message(scan.Bytes())
        }   
    }() 
    return lines
}


func main() {
    mes := make (chan message, 1)
    sig := make (chan bool)
    ch := read (os.Stdin) //Reading from Stdin
    for {
        select {
            case anu := <-mes:
                fmt.Println("Message to stdout")
                fmt.Println(string(anu)) //Writing to Stdout
            case mes <- <-ch:
                fmt.Println("Message to channel 2")
                continue
        }   
    }   
    <-sig

/*
The O/P is :

go run writetochan.go 
Golang
Message to channel 2
Fun     <<< Delayed O/P golang means after putting one more 
            message only we are getting First message
Message to stdout
Golang


Expected O/P:
go run writetochan.go 
Golang
Message to channel 2
Message to stdout
Golang
Fun
Message to channel 2

*/
}

想要达到上面显示的O/P。

我们正在从一个通道写入,该通道从用户读取所有标准输入,然后写入标准输出。通道读取发生在 goroutine 中。形成了一个虚拟通道 (sig),这样我们就可以 运行 无限期地使用它(只是现在)。

问题是您在第二个 select 案例中有两个通道操作。 Select 仅防止 outer 操作阻塞。因此 <-ch 调用被立即评估,并且没有 select 的阻塞保护,所以整个 select 语句阻塞直到在该通道上接收到其他东西(这需要另一个输入以便 read() 可以在该频道上再次发送)。

不幸的是,修复不是那么干净。如果将其更改为 case m := <-ch:,则在 mes 上发送 m 将阻塞 select,如果它已经在缓冲区,则可能导致死锁。修复它的最简单方法可能是只有一个通道,而不是两个。示例:

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
)

/* Function to run the groutine to run for stdin read */
func read(r io.Reader) <-chan string {
    lines := make(chan string)
    go func() {
        defer close(lines)
        scan := bufio.NewScanner(r)
        for scan.Scan() {
            lines <- scan.Text()
        }
    }()
    return lines
}

func main() {
    mes := read(os.Stdin) //Reading from Stdin
    for anu := range mes {
        fmt.Println("Message to stdout")
        fmt.Println(anu) //Writing to Stdout
    }
}

请注意,我将您的 scan.Bytes() 调用更改为 scan.Text(),因为 scan.Bytes() 的注释明确指出 returns 切片的底层数组不安全防止被后续扫描调用覆盖。

另一种选择是使用单独的 goroutine 来转换通道之间的消息:

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
)

/* Function to run the groutine to run for stdin read */
func read(r io.Reader) <-chan string {
    lines := make(chan string)
    go func() {
        defer close(lines)
        scan := bufio.NewScanner(r)
        for scan.Scan() {
            s := scan.Text()
            lines <- s
        }
    }()
    return lines
}

func main() {
    mes := make(chan string, 1)
    ch := read(os.Stdin) //Reading from Stdin
    go func() {
        for m := range ch {
            fmt.Println("Message to channel 2")
            mes <- m
        }
    }()
    for anu := range mes {
        fmt.Println("Message to stdout")
        fmt.Println(anu) //Writing to Stdout
    }
}