看书时有这样两段代码,有点疑惑下面是代码
server.go
package ipc
import (
"encoding/json"
"fmt"
)
type Request struct {
Method string
Params string
}
type Response struct {
Code string
Body string
}
type Server interface {
Name() string
Handle(method, params string) *Response
}
type IpcServer struct {
Server
}
func NewIpcServer(server Server) *IpcServer {
return &IpcServer{Server: server}
}
func (server *IpcServer) Connect() chan string {
session := make(chan string)
go func(c chan string) {
for {
request := <-c
if request == "CLOSE" { // 关闭该连接
break
}
var req Request
err := json.Unmarshal([]byte(request), &req)
if err != nil {
fmt.Println("Invalid request format:", request)
}
resp := server.Handle(req.Method, req.Params)
b, _ := json.Marshal(resp)
c <- string(b) // 返回结果
}
fmt.Println("Session closed.")
}(session)
fmt.Println("A new session has been created successfully.")
return session
}
client.go
package ipc
import (
"encoding/json"
)
type IpcClient struct {
conn chan string
}
func NewIpcClient(server *IpcServer) *IpcClient {
c := server.Connect()
return &IpcClient{c}
}
func (client *IpcClient) Call(method, params string) (resp *Response, err error) {
req := &Request{method, params}
var b []byte
b, err = json.Marshal(req)
if err != nil {
return
}
client.conn <- string(b)
str := <-client.conn // 等待返回值
var resp1 Response
err = json.Unmarshal([]byte(str), &resp1)
resp = &resp1
return
}
func (client *IpcClient) Close() {
client.conn <- "CLOSE"
}
我的疑问是在 NewIpcClient()
的时候创建了一个channel并开启了一个协程,call
执行到client.conn <- string(b)
的时候 开启的协程一定开始执行了吗,channel处于等待状态?
c <- string(b) // 返回结果
执行完成的时候,call方法会不会刚好只执行到client.conn <- string(b)
就让出执行时间了,没有执行到str := <-client.conn // 等待返回值
。然后for继续在执行,然后就改返回的response读取到了,继续for循环执行。
或者换种说法,上面代码的写法一定会保证按照server端等待客户端输入,然后返回给客户端,然后server端继续等待客户端。无论代码执行到什么位置,让出执行时间。一定会的话,怎么做到的?
client.conn <- string(b)的时候 开启的协程一定开始执行了吗,channel处于等待状态?
协程开没开始都没关系,但是channel已经建立起来了。
session := make(chan string)
是创建channel的,创建之后,处理这个channel的协程没有开始的话,channel就在阻塞中。
str := <-client.conn // 等待返回值
这一步会一直阻塞,直到client.conn
这个channel有值了,也就是sever的代码中的c <- string(b) // 返回结果
执行之后才会接着执行。
其实整体来看,上面代码中的channel的缓冲只有一个元素,完全可以当成同步的代码来看。
server接收了一个请求后,直至处理完,不能再接收其他请求了。