Golang - 为 select 语句使用两个 Reader 返回行
Golang - use two Reader returned lines for select statement
对于一个简单的 golang chat/telnet 客户端,我想将从两个 bufio Reader 接收到的字符串传递给一个 select 语句,这样我就可以将用户输入发送到服务器,或者打印服务器发送的数据。
conn, _ := net.Dial("tcp", "localhost:8998")
for {
select{
case line, _ := bufio.NewReader(os.Stdin).ReadString('\n'):
fmt.Print("> ")
fmt.Fprintf(conn, line + "\n")
case data, _ := bufio.NewReader(conn).ReadString('\n'):
fmt.Print(data)
}
}
编译器返回这个错误
select case must be receive, send or assign recv
我怀疑我应该使用频道。但是
conn, _ := net.Dial("tcp", "localhost:8998")
outgoing := make(chan string)
incoming := make(chan string)
for {
inputReader := bufio.NewReader(os.Stdin)
connReader := bufio.NewReader(conn)
o, _ := inputReader.ReadString('\n')
i, _ := connReader.ReadString('\n')
outgoing <- o
incoming <- i
select{
case out := <-outgoing:
fmt.Print("> ")
fmt.Fprintf(conn, out + "\n")
case in := <-incoming:
fmt.Print(in)
}
}
但是代码不接受或接收数据。最后,我怀疑我应该使用两个 go 例程来检查 Reader return 值?
你需要在 goroutines 中 运行 它们,否则它们不能同时发生:
conn, _ := net.Dial("tcp", "localhost:8998")
// Make outgoing reader routine
outgoing := make(chan string)
go func() {
inputReader := bufio.NewReader(os.Stdin)
for {
o, err := inputReader.ReadString('\n')
if err != nil {
fmt.Printf("outgoing error: %v", err)
return
}
outgoing <- o
}
}()
// Make incoming reader routine
incoming := make(chan string)
go func() {
connReader := bufio.NewReader(conn)
for {
i, err := connReader.ReadString('\n')
if err != nil {
fmt.Printf("incoming error: %v", err)
return
}
incoming <- i
}
}()
for {
select {
case out := <-outgoing:
fmt.Print("> ")
fmt.Fprintf(conn, out+"\n")
case in := <-incoming:
fmt.Print(in)
}
}
编辑
进一步详细说明:您的第一个示例将不起作用,因为 select
要求每个案例要么是通道读取操作,要么是通道发送操作,而函数调用 bufio.Reader.ReadString()
两者都不是。
您的第二个示例将不起作用,因为行 outgoing <- o
将无限期阻塞。它试图通过通道 outgoing
发送 o
,但是 outgoing
没有被缓冲,并且没有任何东西在它上面监听。此外,由于在读取一行之前 ReadString()
调用都不会 return,因此只有从 BOTH 读者读取一行后,您的 for
循环才会继续依次(然后将阻止通道发送)。
这就是为什么您需要每个 Reader 都有自己的 goroutine,这样每个人都可以在输入允许的情况下独立读取其 Reader,并在读取行时将其存储到相关通道,并且然后,您的 select
语句可以对来自各个 goroutine 的每一行做出反应。
对于一个简单的 golang chat/telnet 客户端,我想将从两个 bufio Reader 接收到的字符串传递给一个 select 语句,这样我就可以将用户输入发送到服务器,或者打印服务器发送的数据。
conn, _ := net.Dial("tcp", "localhost:8998")
for {
select{
case line, _ := bufio.NewReader(os.Stdin).ReadString('\n'):
fmt.Print("> ")
fmt.Fprintf(conn, line + "\n")
case data, _ := bufio.NewReader(conn).ReadString('\n'):
fmt.Print(data)
}
}
编译器返回这个错误
select case must be receive, send or assign recv
我怀疑我应该使用频道。但是
conn, _ := net.Dial("tcp", "localhost:8998")
outgoing := make(chan string)
incoming := make(chan string)
for {
inputReader := bufio.NewReader(os.Stdin)
connReader := bufio.NewReader(conn)
o, _ := inputReader.ReadString('\n')
i, _ := connReader.ReadString('\n')
outgoing <- o
incoming <- i
select{
case out := <-outgoing:
fmt.Print("> ")
fmt.Fprintf(conn, out + "\n")
case in := <-incoming:
fmt.Print(in)
}
}
但是代码不接受或接收数据。最后,我怀疑我应该使用两个 go 例程来检查 Reader return 值?
你需要在 goroutines 中 运行 它们,否则它们不能同时发生:
conn, _ := net.Dial("tcp", "localhost:8998")
// Make outgoing reader routine
outgoing := make(chan string)
go func() {
inputReader := bufio.NewReader(os.Stdin)
for {
o, err := inputReader.ReadString('\n')
if err != nil {
fmt.Printf("outgoing error: %v", err)
return
}
outgoing <- o
}
}()
// Make incoming reader routine
incoming := make(chan string)
go func() {
connReader := bufio.NewReader(conn)
for {
i, err := connReader.ReadString('\n')
if err != nil {
fmt.Printf("incoming error: %v", err)
return
}
incoming <- i
}
}()
for {
select {
case out := <-outgoing:
fmt.Print("> ")
fmt.Fprintf(conn, out+"\n")
case in := <-incoming:
fmt.Print(in)
}
}
编辑
进一步详细说明:您的第一个示例将不起作用,因为 select
要求每个案例要么是通道读取操作,要么是通道发送操作,而函数调用 bufio.Reader.ReadString()
两者都不是。
您的第二个示例将不起作用,因为行 outgoing <- o
将无限期阻塞。它试图通过通道 outgoing
发送 o
,但是 outgoing
没有被缓冲,并且没有任何东西在它上面监听。此外,由于在读取一行之前 ReadString()
调用都不会 return,因此只有从 BOTH 读者读取一行后,您的 for
循环才会继续依次(然后将阻止通道发送)。
这就是为什么您需要每个 Reader 都有自己的 goroutine,这样每个人都可以在输入允许的情况下独立读取其 Reader,并在读取行时将其存储到相关通道,并且然后,您的 select
语句可以对来自各个 goroutine 的每一行做出反应。