一、简单的web server
使用Go创建HTTP服务器,实现一个返回”Hello World!”的web server
1 2 3 4 5 6 7 8 9 10 11 12 13
| package main
import ( "fmt" "net/http" )
func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") }) http.ListenAndServe(":80", nil) }
|
运行此程序并用浏览器打开到http://localhost
,将看到” Hello World!”
二、使用net/http
net/http中主要的三个部分:http.Handler、http.ServeMux、http.server
1 2 3
| type Handler interface { ServeHTTP(ResponseWriter, *Request) }
|
三、加密
Go中使用HTTPS,如果拥有私钥和证书,可以更改服务器以使用ListenAndServeTLS并提供正确的文件路径
1
| http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)
|
打开浏览器,https://example.com
将显示“”Hello World!”
四、增加处理
创建通配符路由以及在路由中添加参数或模式匹配。
首先,建一个名为api/router/api.go
的文件,其中包含API的路由:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| // 自定义JSON消息格式 type HelloResponse struct { Message string `json:"message"` }
// 返回JSON信息 func HelloName(w http.ResponseWriter, r *http.Request) { name := chi.URLParam(r, "name") response := HelloResponse{ Message: fmt.Sprintf("Hello %s!", name), } jsonResponse(w, response, http.StatusOK) }
// 返回一个HTTP处理程序,实现API的路由 func NewRouter() http.Handler { r := chi.NewRouter() r.Get("/{name}", HelloName) return r }
|
然后,可以将其挂载到api/router/
主应用程序中的前缀下方的主路由器中:
1 2 3 4 5 6 7
| // 返回一个新的HTTP处理程序,实现主服务器路由 func NewRouter() http.Handler { router := chi.NewRouter() router.Mount("/api/router/", v1.NewRouter()) return router } http.Serve(autocert.NewListener("example.com"), NewRouter())
|
五、中间件
中间件只是将HTTP处理程序包装在另一个处理程序中。这可以实现身份验证,日志记录,压缩等功能。写一些带有处理程序并将其包装在另一个处理程序中的函数。
例如显示了如何实现身份验证处理程序:
1 2 3 4 5 6 7 8 9 10
| func RequireAuthentication(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !isAuthenticated(r) { http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) return } // 通过了身份验证,请运行原始处理程序 next.ServeHTTP(w, r) }) }
|
六、静态文件
Golang的标准库中支持提供静态文件,例如图像,Javascript和样式表。是通过使用函数http.FileServer返回一个处理程序来完成的,该处理程序为目录中的文件提供服务。
简单的路由例子:
1 2 3 4 5 6 7 8 9 10 11
| func NewRouter() http.Handler { router := chi.NewRouter() r.Get("/{name}", HelloName)
// 设置静态文件 staticPath, _ := filepath.Abs("../../static/") fs := http.FileServer(http.Dir(staticPath)) router.Handle("/*", fs) return r }
|
七、最后
Go 1.8版本以后引入了通过调用Shutdown()方法正常关闭HTTP服务器的功能。通过在goroutine中启动服务器并在通道上侦听信号中断,使用此功能在收到此消息后,给服务器几秒钟的时间来正常关闭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| handler := server.NewRouter() srv := &http.Server{ Handler: handler, }
go func() { srv.Serve(autocert.NewListener(domains...)) }()
// 等待中断 c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) <-c
// 尝试正常关闭 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() srv.Shutdown(ctx)
|