并发 |协程 |语言 |缓冲 reader
concurrency | goroutines | golang | buffered reader
相信 我要么误解了 go 例程的工作方式,缓冲 readers 的工作方式,要么两者都有。
Expect goroutine 的异步执行(缓冲 reader 带有 for 循环读取缓冲区,等待来自服务器的消息)
尝试METHOD A
在客户端拨通服务器之前调用go xyz()
;所以 xyz()
创建缓冲区并开始在后台读取。然后,客户端拨通服务器;服务器发回消息;客户端正在读取缓冲区,因此它获取消息并打印到控制台
实际发生了什么 客户端向服务器发送消息,但在读取服务器可能的回复时没有从缓冲区中获取任何内容;所以它是 运行 同时因为我知道 for 循环没有停止,但它让下一行代码执行(客户端向服务器发送消息)。
但是当 METHOD B
我调用 xyz()
NOT 并发并且在客户端拨打服务器之后,所有事情都按预期工作。客户端从服务器获取消息并打印到控制台。
方法A,我们有顺序:
////////////步骤1和2在[=调用的goroutine中14=]
- 创建缓冲 reader
- for 循环 -- 从服务器读取消息缓冲区 -- 打印出来
客户端拨打服务器
go xyz(conn, p)
fmt.Fprintf(conn, "Give me a hash to work on ...")
方法 B,我们有顺序:
/////////////第2步和第3步在[=调用的goroutine中15=]
- 客户端拨打服务器
- 创建缓冲 reader
for 循环 -- 从服务器读取消息缓冲区 -- 打印出来
fmt.Fprintf(conn, "Give me a hash to work on ...")
xyz(conn, p)
client.go
package main
import (
"fmt"
"net"
"bufio"
)
func xyz(conn net.Conn, p []byte) {
rd := bufio.NewReader(conn)
for {
_, err := rd.Read(p)
if err == nil {
fmt.Printf("SERVER : %s\n", p)
} else {
fmt.Printf("Some error %v\n", err)
}
}
}
func main() {
p := make([]byte, 2048)
conn, err := net.Dial("udp", "127.0.0.1:1234")
if err != nil {
fmt.Printf("Some error %v", err)
return
}
go xyz(conn, p)
fmt.Fprintf(conn, "Give me a hash to work on ...")
}
server.go
package main
import (
"fmt"
"net"
)
func sendResponse(conn *net.UDPConn, addr *net.UDPAddr, hash string) {
_,err := conn.WriteToUDP([]byte("Hello, here is the hash - " + hash), addr)
if err != nil {
fmt.Printf("Couldn't send response %v", err)
}
}
func main() {
hash := "36";
p := make([]byte, 2048)
addr := net.UDPAddr{
Port: 1234,
IP: net.ParseIP("127.0.0.1"),
}
ser, err := net.ListenUDP("udp", &addr)
if err != nil {
fmt.Printf("Some error %v\n", err)
return
}
for {
_, remoteaddr, err := ser.ReadFromUDP(p)
fmt.Printf("CLIENT : %v : %s\n", remoteaddr, p)
if err != nil {
fmt.Printf("Some error %v", err)
continue
}
go sendResponse(ser, remoteaddr, hash)
}
}
The Go Programming Language Specification
A "go" statement starts the execution of a function call as an
independent concurrent thread of control, or goroutine, within the
same address space.
... unlike with a regular call, program execution does not wait for
the invoked function to complete.
client.go
启动 goroutine xyz
然后继续运行到终止程序的 main
函数的末尾。该程序不会等待 xyz
goroutine 运行 或完成。
相信 我要么误解了 go 例程的工作方式,缓冲 readers 的工作方式,要么两者都有。
Expect goroutine 的异步执行(缓冲 reader 带有 for 循环读取缓冲区,等待来自服务器的消息)
尝试METHOD A
在客户端拨通服务器之前调用go xyz()
;所以 xyz()
创建缓冲区并开始在后台读取。然后,客户端拨通服务器;服务器发回消息;客户端正在读取缓冲区,因此它获取消息并打印到控制台
实际发生了什么 客户端向服务器发送消息,但在读取服务器可能的回复时没有从缓冲区中获取任何内容;所以它是 运行 同时因为我知道 for 循环没有停止,但它让下一行代码执行(客户端向服务器发送消息)。
但是当 METHOD B
我调用 xyz()
NOT 并发并且在客户端拨打服务器之后,所有事情都按预期工作。客户端从服务器获取消息并打印到控制台。
方法A,我们有顺序:
////////////步骤1和2在[=调用的goroutine中14=]
- 创建缓冲 reader
- for 循环 -- 从服务器读取消息缓冲区 -- 打印出来
客户端拨打服务器
go xyz(conn, p)
fmt.Fprintf(conn, "Give me a hash to work on ...")
方法 B,我们有顺序:
/////////////第2步和第3步在[=调用的goroutine中15=]
- 客户端拨打服务器
- 创建缓冲 reader
for 循环 -- 从服务器读取消息缓冲区 -- 打印出来
fmt.Fprintf(conn, "Give me a hash to work on ...")
xyz(conn, p)
client.go
package main
import (
"fmt"
"net"
"bufio"
)
func xyz(conn net.Conn, p []byte) {
rd := bufio.NewReader(conn)
for {
_, err := rd.Read(p)
if err == nil {
fmt.Printf("SERVER : %s\n", p)
} else {
fmt.Printf("Some error %v\n", err)
}
}
}
func main() {
p := make([]byte, 2048)
conn, err := net.Dial("udp", "127.0.0.1:1234")
if err != nil {
fmt.Printf("Some error %v", err)
return
}
go xyz(conn, p)
fmt.Fprintf(conn, "Give me a hash to work on ...")
}
server.go
package main
import (
"fmt"
"net"
)
func sendResponse(conn *net.UDPConn, addr *net.UDPAddr, hash string) {
_,err := conn.WriteToUDP([]byte("Hello, here is the hash - " + hash), addr)
if err != nil {
fmt.Printf("Couldn't send response %v", err)
}
}
func main() {
hash := "36";
p := make([]byte, 2048)
addr := net.UDPAddr{
Port: 1234,
IP: net.ParseIP("127.0.0.1"),
}
ser, err := net.ListenUDP("udp", &addr)
if err != nil {
fmt.Printf("Some error %v\n", err)
return
}
for {
_, remoteaddr, err := ser.ReadFromUDP(p)
fmt.Printf("CLIENT : %v : %s\n", remoteaddr, p)
if err != nil {
fmt.Printf("Some error %v", err)
continue
}
go sendResponse(ser, remoteaddr, hash)
}
}
The Go Programming Language Specification
A "go" statement starts the execution of a function call as an independent concurrent thread of control, or goroutine, within the same address space.
... unlike with a regular call, program execution does not wait for the invoked function to complete.
client.go
启动 goroutine xyz
然后继续运行到终止程序的 main
函数的末尾。该程序不会等待 xyz
goroutine 运行 或完成。