我需要发送3次echo aaa
到Redis服务器,
但它卡在过程的中间,我也检查
如果read
和write
操作收到错误消息,但没有。
那么,为什么它卡在过程的中间?
package main
import (
"fmt"
"os"
"io"
"net"
"sync"
)
var (
wg = new(sync.WaitGroup)
)
func readFromServer(isWrite chan bool, r io.Reader) {
for {
select {
case <-isWrite:
_ , err := io.Copy(os.Stdout, r)
if err != nil {
panic(err)
}
}
}
}
func writeToServer(conn net.Conn , isWrite chan bool ){
defer wg.Done()
for i :=0; i<3; i++{
_ , err := conn.Write([]byte("*2\r\n$4\r\necho\r\n$3\r\naaa\r\n"))
if err != nil {
panic(err)
}
isWrite<- true
}
}
func main(){
wg.Add(1)
conn ,err := net.Dial("tcp","127.0.0.1:6379")
isWrite := make(chan bool)
if err != nil {
panic(err)
}
go readFromServer(isWrite, conn)
go writeToServer(conn , isWrite)
wg.Wait()
fmt.Println("finished...")
}
输出:
$3
aaa
$3
aaa
Stuck here...
答案 0 :(得分:1)
readFromServer函数从isWrite通道接收一个值,然后阻止对io.Copy的调用。 io.Copy函数直到EOF或某些错误读取或写入数据后才返回。所有程序输出均来自对io.Copy的单次调用。
在sendToServer块中第二个发送到isWrite。 isWrite通道是一个无缓冲通道。直到有接收方,才会在无缓冲通道上进行发送。通道上没有接收器,因为对io.Copy的调用中阻止了readFromServer。
可能的解决方法是:
解决方法是修改readFromServer以解析RESP协议,并在循环中每次迭代恰好读取一条消息。
通过一次调用io.Copy替换readFromServer中的循环。
不需要isWrite通道。
程序无法确保readFromServer在程序退出之前从writeToServer读取所有响应。