想要使用通道从 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
}
}
/* 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
}
}