像在Nodejs语言里端口监听建立成功时会触发一个事件来执行相应的代码,而在Go里面如果直接使用ListenAndServe函数的话是没办法知道端口监听是何时建立成功的。ListenAndServe包含两步操作:1)监听端口 2)accept以阻塞方式等待接受请求;如果1)执行成功,会立即进入阻塞状态,后面的代码在shutdown之前都无法执行,所以如果想在端口监听成功时输出一条日志,则
需要单独建立net.Listener再传给Serve函数,具体代码如下:
package main
import (
"context"
"fmt"
"log"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
//http://pub.funshion.com:1341/service
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello")
}
func main() {
start := time.Now()
port := "1341"
srv := http.Server{
Addr: ":" + port,
Handler: http.DefaultServeMux,
}
http.HandleFunc("/", handler)
//gracefully shutdown
go func() {
sigint := make(chan os.Signal, 1)
signal.Notify(sigint, syscall.SIGINT, syscall.SIGTERM)
data := <-sigint
log.Printf("received signal: " + data.String())
log.Printf("start to shutdown...")
if err := srv.Shutdown(context.Background()); err != nil {
log.Fatalf("HTTP server Shutdown: %v", err)
}
}()
//listen
ln, err := net.Listen("tcp", srv.Addr)
if err != nil {
log.Fatalf(err.Error())
return
}
log.Printf("listen on %s", port)
log.Printf("time elapse: %d ms", time.Now().Sub(start).Milliseconds())
//serve
err = srv.Serve(ln)
if err != nil && err != http.ErrServerClosed {
log.Fatalf("server error: %v", err)
} else {
log.Printf("successfully shutdown: %v", err)
}
}