大家好,我是 polarisxu。
和静网站制作公司哪家好,找成都创新互联!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设公司等网站项目制作,到程序开发,运营维护。成都创新互联自2013年创立以来到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联。
os/signal 这个包大家可能用的不多。但自从 Go1.8 起,有些人开始使用这个包了,原因是 Go1.8 在 net/http 包新增了一个方法:
- func (srv *Server) Shutdown(ctx context.Context) error
有了它就不需要借助第三方库实现优雅关闭服务了。具体怎么做呢?
- func main() {
- server = http.Server{
- Addr: ":8080",
- }
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- time.Sleep(time.Second * 10)
- fmt.Fprint(w, "Hello world!")
- })
- go server.ListenAndServe()
- // 监听中断信号(CTRL + C)
- c := make(chan os.Signal, 1)
- signal.Notify(c, os.Interrupt)
- <-c
- // 重置 os.Interrupt 的默认行为
- signal.Reset(os.Interrupt)
- fmt.Println("shutting down gracefully, press Ctrl+C again to force")
- // 给程序最多 5 秒时间处理正在服务的请求
- timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- if err := server.Shutdown(timeoutCtx); err != nil {
- fmt.Println(err)
- }
- }
优雅退出的关键:1)新请求进不来;2)已有请求给时间处理完。所以,在接收到信号后,调用 server.Shutdown 方法,阻止新请求进来,同时给 5 秒等待时间,让已经进来的请求有时间处理。
在 Go1.16 中,os/signal 包新增了一个函数:
- func NotifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc)
功能和 Notify 类似,但用法上有些不同。上面的例子改用 NotifyContext:
- func after() {
- server = http.Server{
- Addr: ":8080",
- }
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- time.Sleep(time.Second * 10)
- fmt.Fprint(w, "Hello world!")
- })
- go server.ListenAndServe()
- // 监听中断信号(CTRL + C)
- ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
- <-ctx.Done()
- // 重置 os.Interrupt 的默认行为,类似 signal.Reset
- stop()
- fmt.Println("shutting down gracefully, press Ctrl+C again to force")
- // 给程序最多 5 秒时间处理正在服务的请求
- timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- if err := server.Shutdown(timeoutCtx); err != nil {
- fmt.Println(err)
- }
- }
和上面的写法有区别,完成的功能一样的。其实 NotifyContext 的内部就是基于 Notify 实现的:
- func NotifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc) {
- ctx, cancel := context.WithCancel(parent)
- c := &signalCtx{
- Context: ctx,
- cancel: cancel,
- signals: signals,
- }
- c.ch = make(chan os.Signal, 1)
- Notify(c.ch, c.signals...)
- if ctx.Err() == nil {
- go func() {
- select {
- case <-c.ch:
- c.cancel()
- case <-c.Done():
- }
- }()
- }
- return c, c.stop
- }
只是在返回的 stop 被调用时,会执行 os/signal 包中的 Stop 函数,这个 Stop 函数的功能和 Reset 类似。因此上面 Notify 的例子,Reset 的地方可以改为 Stop。
从封装上看,NotifyContext 做的更好。而且,如果在某些需要 Context 的场景下,它把监控系统信号和创建 Context 一步搞定。
NotifyContext 的用法,优雅的关闭服务,你掌握了吗?希望你实际动手试验下,启动服务,通过 curl http://localhost:8080/ 访问,然后按 CTRL + C,看看具体效果。只看不动手,基本知识不是你的。
关于 NotifyContext 函数的文档可以在这里查看:https://docs.studygolang.com/pkg/os/signal/#NotifyContext。
本文转载自微信公众号「polarisxu」,可以通过以下二维码关注。转载本文请联系polarisxu公众号。
当前题目:Go1.16中的新函数Signal.NotifyContext怎么用?
文章源于:http://www.36103.cn/qtweb/news31/32881.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联