go - 如何编写在 goroutines 中执行的函数来发送和接收消息?
问题描述
我必须编写一个客户端代码,它以字符串的形式从服务器接收消息,并从控制台获取输入以结束消息到服务器。这两个操作应该彼此同时运行。我编写了一个代码来执行这些操作,但不是同时执行。
这是我当前的代码的样子:
func SocketClient() {
conn, err := net.Dial("tcp", ":9000")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
server_reader := bufio.NewReader(conn)
input_reader := bufio.NewReader(os.Stdin)
for {
// for sending messages
buff, err := input_reader.ReadString('\n')
if err != nil {
log.Fatalln(err)
}
conn.Write([]byte(buff))
// for receiving messages but this won't run until the above has taken input from console
buff2, err := server_reader.ReadString('\n')
if err != nil {
log.Fatalln(err)
}
fmt.Println("Received: %s", buff2)
}
}
buff 接收来自服务器的传入消息,然后 buff2 从控制台接收传出消息输入,但为了再次接收传入消息,buff2 需要一些输入。我知道这可以使用通道、互斥锁等来完成,但是由于我对基础知识缺乏了解,我在使用它们时遇到了问题。
我想实际的代码应该是这样的:
func SocketClient() {
conn, err := net.Dial("tcp", ":9000")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
go func() {
// for sending messages
} ()
go func() {
// for receiving messages
} ()
}
如何将输入和输出作为两个独立的 goroutine?
解决方案
直接在 中运行其中一个循环SocketClient
。在由SocketClient
.
func SocketClient() error {
conn, err := net.Dial("tcp", ":9000")
if err != nil {
return err
}
defer conn.Close()
server_reader := bufio.NewReader(conn)
input_reader := bufio.NewReader(os.Stdin)
go func() {
defer conn.Close()
// This loop will break and the goroutine will exit when the
// SocketClient function executes conn.Close().
for {
buff, err := server_reader.ReadBytes('\n')
if err != nil {
// optional: log.Fatal(err) to cause program to exit without waiting for new input from stdin.
return
}
fmt.Printf("Received: %s", buff)
}
}()
for {
// for sending messages
buff, err := input_reader.ReadBytes('\n')
if err != nil {
return err
}
if _, err := conn.Write(buff); err != nil {
return err
}
}
}
使用 bufio.ReaderReadBytes
方法而不是ReadString
避免[]byte
和之间不必要的转换string
。
推荐阅读
- r - 使用 geom_smooth() 绘图时使用 Theil-Sen 方法
- django - 创建将更改模型中的 BooleanField 的 Django HTML 按钮
- python - Django和docker中.env文件中的环境变量
- algorithm - N个移动点之间的最短距离
- java - 如何在java中创建具有不同语言名称的目录?
- html - 文章与部分。在这种情况下应该使用哪一个?
- reactjs - Reactjs路由css问题
- azure - 带有两个 csv 文件的 Azure terraform 参数不起作用
- python - 在没有库的情况下计算 ROC 的不同阈值
- excel - 将 excel 中的名称与中间名和额外空格匹配