这段代码的goroutine有一点疑惑,求解
func (client *Client) receive() {
var err error
for err == nil {
var h codec.Header
if err = client.cc.ReadHeader(&h); err != nil {
break
}
call := client.removeCall(h.Seq)
switch {
case call == nil:
// it usually means that Write partially failed
// and call was already removed.
err = client.cc.ReadBody(nil)
case h.Error != "":
call.Error = fmt.Errorf(h.Error)
err = client.cc.ReadBody(nil)
call.done()
default:
err = client.cc.ReadBody(call.Reply)
if err != nil {
call.Error = errors.New("reading body " + err.Error())
}
call.done()
}
}
// error occurs, so terminateCalls pending calls
client.terminateCalls(err)
}
func NewClient(conn net.Conn, opt *Option) (*Client, error) {
f := codec.NewCodecFuncMap[opt.CodecType]
if f == nil {
err := fmt.Errorf("invalid codec type %s", opt.CodecType)
log.Println("rpc client: codec error:", err)
return nil, err
}
// send options with server
if err := json.NewEncoder(conn).Encode(opt); err != nil {
log.Println("rpc client: options error: ", err)
_ = conn.Close()
return nil, err
}
return newClientCodec(f(conn), opt), nil
}
func newClientCodec(cc codec.Codec, opt *Option) *Client {
client := &Client{
seq: 1, // seq starts with 1, 0 means invalid call
cc: cc,
opt: opt,
pending: make(map[uint64]*Call),
}
go client.receive()
return client
}
这是rpc的一段客户端的的一段代码,这里newClientCodec()
返回后go client.receive()
怎么能保证一直运行接受请求,主线程运行完coroutine也会终止啊
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这没啥问题吧?只要主线程生命周期比这个 goroutine 长就行了。
如果主线程代码是你自己写的,要么
sync.WaitGroup
去等 goroutine,要么阻塞掉主线程等信号就好了啊要是主线程调用 listen 之类的网络 api 阻塞住了,就更不用管了。
除非知道主线程在特定情况下会退出,然后你又想主线程不要马上退出,先等 goroutine 处理完或保存好数据,也就是所谓的优雅停机 graceful shutdown 。
这种情况可以监听
SIGINT
、SIGTERM
信号,SIGINT
在键盘按下ctrl+c
触发,SIGTERM
会在kill
命令、Docker 停止容器等情况下触发。在信号处理阶段用context
、sync.WaitGroup
让 goroutine 把手里的事情处理完再退出,完成 graceful shutdown。