/**
Go 语言中实现优雅的停止程序
主goroutine监听操作系统消息,收到系统停止消息后关闭server的chan,所有子协程检测到chan关闭,则全部退出
**/
package main
import (
"log"
"net"
"os"
"os/signal"
"sync"
"syscall"
"time"
)
// An uninteresting service.
type Service struct {
ch chan bool
waitGroup *
}
// Make a new Service.
func NewService() *Service {
return &Service{
ch: make(chan bool),
waitGroup: &{},
}
}
// Accept connections and spawn a goroutine to serve each one. Stop listening
// if anything is received on the service's channel.
func (s *Service) Serve(listener *) {
(1)
defer ()
for {
select {
case <-:
("stopping listening on", ())
()
return
default:
}
(().Add(1e9))
conn, err := ()
if nil != err {
//判断错误类型是否是
if opErr, ok := err.(*); ok && () {
continue
}
(err)
}
((), "connected")
go (conn)
}
}
// Stop the service by closing the service's channel. Block until the service
// is really stopped.
func (s *Service) Stop() {
close()
()
}
// Serve a connection by reading and writing what was read. That's right, this
// is an echo service. Stop reading and writing if anything is received on the
// service's channel but only after writing what was read.
func (s *Service) serve(conn *) {
defer ()
(1)
defer ()
for {
select {
case <-:
("disconnecting", ())
return
default:
}
(().Add(1e9))
buf := make([]byte, 4096)
if _, err := (buf); nil != err {
if opErr, ok := err.(*); ok && () {
continue
}
(err)
return
}
if _, err := (buf); nil != err {
(err)
return
}
}
}
func main() {
// Listen on 127.0.0.1:48879. That's my favorite port number because in
// hex 48879 is 0xBEEF.
laddr, err := ("tcp", "127.0.0.1:48879")
if nil != err {
(err)
}
listener, err := ("tcp", laddr)
if nil != err {
(err)
}
("listening on", ())
// Make a new service and send it into the background.
service := NewService()
go (listener)
// Handle SIGINT and SIGTERM.
ch := make(chan )
(ch, , )
("signal:", <-ch)
// Stop the service gracefully.
()
}