
一边监听客户端连接一边监听终端输入的go代码实践
在go中构建一个可同时监听客户端连接和终端输入的服务器程序需要解决并发更新和阻塞问题。
问题背景
在最初的代码中,服务端通过阻塞性的fmt.scan 读取终端输入。这会导致监听客户端连接的goroutine长期阻塞,无法正常响应新连接请求。
优化方案
为了解决问题,需要使用非阻塞方式读取终端输入。改进后的代码如下:
package main
import (
"fmt"
"os"
)
var recvFromTerminalChan = make(chan string)
var recvFromNetChan = make(chan string)
func main() {
go readFromTerminal()
for {
select {
// 从终端输入通道接收数据
case str := <-recvFromTerminalChan:
go sendCommandToNet(str)
// 从网络通道接收数据
case str := <-recvFromNetChan:
go doContentFromNet(str)
}
}
}
func readFromTerminal() {
for {
var input string
fmt.Scan(&input)
fmt.Println("input content:", input)
recvFromTerminalChan <- input
}
}
func sendCommandToNet(command string) {
fmt.Println("command:", command)
content := command
recvFromNetChan <- content
}
func doContentFromNet(content string) {
fmt.Println("content from net:", content)
}改进要点
- 使用make(chan string)创建无缓冲通道recvfromterminalchan,用于接收终端输入。
- 将fmt.scan调用移入协程readfromterminal。
- 在readfromterminal协程中,通过recvfromterminalchan发送输入数据。
这样,服务器程序就能一边通过通道接收终端输入,一边通过goroutine监听客户端连接。select语句确保了程序不会因任一通道阻塞而死锁。










