/* 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。
我们正在从一个 channel 写入,该 channel 从用户读取所有标准输入,然后写入标准输出。 channel 读取发生在 goroutine 中。形成了一个虚拟 channel (sig),以便我们可以无限期地运行它(只是现在)。
最佳答案
问题是您在第二个 select
中有两个 channel 操作案件。 Select 仅防止外部 操作被阻塞。因此 <-ch
call 被立即评估,并且没有 select 的阻塞保护,因此整个 select 语句阻塞,直到在该 channel 上收到其他内容(这需要另一个输入,以便 read()
可以在该 channel 上再次发送)。
不幸的是,修复不是那么干净。如果将其更改为 case m := <-ch:
, 然后发送 m
在 mes
将阻止选择,如果它已经在缓冲区,则可能导致死锁。修复它的最简单方法可能是只有一个 channel ,而不是两个。示例:
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()
的评论特别说明它返回的 slice 的底层数组对于被后续 Scan 调用覆盖是不安全的。
另一种选择是使用单独的 goroutine 来翻译 channel 之间的消息:
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
}
}
关于go - 想要使用 channel 从 os.Stdin 写入 os.Stdout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43610646/