请在Chrome、Firefox等现代浏览器浏览本站。另外提供付费解决DEDE主题修改定制等技术服务,如果需要请 加我 QQ 说你的需求。

Go Web 编程之 程序结构

培训故事

一个典型的 Go Web 程序结构如下,摘自《Go Web 编程》:本文介绍怎样创立多路复用器,怎样注册处理器,终究再简略介绍一下 URL 匹配。咱们以上一篇文......

一个典型的 Go Web 程序结构如下,摘自《Go Web 编程》:

本文介绍怎样创立多路复用器,怎样注册888集团登录处理器,终究再简略介绍一下 URL 匹配。咱们以上一篇文章中的 Hello World 程序作为基础。

package main
import  {
 fmt.Fprintf
func main {
 http.HandleFunc
 if err := http.ListenAndServe; err != nil {
 log.Fatal
仿制代码

net/http 包为了便利咱们运用,内置了一个默许的多路复用器DefaultServeMux。界说如下:

// src/net/http/server.go
// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = defaultServeMux
var defaultServeMux ServeMux
仿制代码

这儿给咱们介绍一下 Go 规范库代码的安排办法,便于咱们对照。

net/http 包中许多办法都在内部调用DefaultServeMux的对应办法,如HandleFunc。咱们知道,HandleFunc是为指定的 URL 注册一个处理器。其内部完成如下:

// src/net/http/server.go
func HandleFunc) {
 DefaultServeMux.HandleFunc
仿制代码

实际上,http.HandleFunc办法是将处理器注册到DefaultServeMux中的。

别的,咱们运用 :8080 和 nil 作为参数调用http.ListenAndServe时,会创立一个默许的服务器:

// src/net/http/server.go
func ListenAndServe {
 server := Server{Addr: addr, Handler: handler}
 return server.ListenAndServe
仿制代码

这个服务器默许运用DefaultServeMux来处理器恳求:

type serverHandler struct {
 srv *Server
func  ServeHTTP {
 handler := sh.srv.Handler
 if handler == nil {
 handler = DefaultServeMux
 handler.ServeHTTP
仿制代码

服务器收到的每个恳求会调用对应多路复用器的ServeHTTP办法。在ServeMux的ServeHTTP办法中,依据 URL 查找咱们注册的处理器,然后将恳求交由它处理。

尽管默许的多路复用器运用起来很便利,可是在出产环境中不主张运用。由于DefaultServeMux是一个全局变量,一切代码,包含第三方代码都能够修正它。 有些第三方代码会在DefaultServeMux注册一些处理器,这可能与咱们注册的处理器抵触。

比较引荐的做法是自己创立多路复用器。

创立多路复用器也比较简略,直接调用http.NewServeMux办法即可。然后,在新创立的多路复用器上注册处理器:

package main
import  {
 fmt.Fprintf
func main {
 mux := http.NewServeMux
 mux.HandleFunc
 server := http.Server{
 Addr: :8080 ,
 Handler: mux,
 if err := server.ListenAndServe; err != nil {
 log.Fatal
仿制代码

上面代码的功能与 Hello World 程序相同。这儿咱们还自己创立了服务器目标。经过指定服务器的参数,咱们能够创立定制化的服务器。

server := http.Server{
 Addr: :8080 ,
 Handler: mux,
 ReadTimeout: 1 * time.Second,
 WriteTimeout: 1 * time.Second,
仿制代码

在上面代码,咱们创立了一个读超时和写超时均为 1s 的服务器。

上文中说到,服务器收到恳求后,会依据其 URL 将恳求交给相应的处理器处理。处理器是完成了Handler接口的结构,Handler接口界说在 net/http 包中:

// src/net/http/server.go
type Handler interface {
 func ServeHTTP
仿制代码

咱们能够界说一个完成该接口的结构,注册这个结构类型的目标到多路复用器中:

package main
import  ServeHTTP {
 fmt.Fprintf
func main {
 mux := http.NewServeMux
 mux.Handle
 mux.Handle
 server := http.Server {
 Addr: :8080 ,
 Handler: mux,
 if err := server.ListenAndServe; err != nil {
 log.Fatal
仿制代码

与前面的代码有所不同,上段代码中,界说了一个完成Handler接口的结构GreetingHandler。然后,创立该结构的两个目标,别离将它注册到多路复用器的/hello和/world途径上。留意,这儿注册运用的是Handle办法,留意与HandleFunc办法比照。

发动服务器之后,在浏览器的地址栏中输入localhost:8080/chinese,浏览器中将显现你好,输入localhost:8080/english将显现Hello。

尽管,自界说处理器这种办法比较灵敏,强壮,可是需求界说一个新的结构,完成ServeHTTP办法,仍是比较繁琐的。为了便利运用,net/http 包供给了以函数的办法注册处理器,即运用HandleFunc注册。函数有必要满意签名:func 。 咱们称这个函数为处理器函数。咱们的 Hello World 程序中运用的便是这种办法。HandleFunc办法内部,会将传入的处理器函数转换为HandlerFunc类型。

// src/net/http/server.go
func  HandleFunc) {
 if handler == nil {
 panic
 mux.Handle)
仿制代码

HandlerFunc是底层类型为func 的新类型,它能够自界说其办法。由于HandlerFunc类型完成了Handler接口,所以它也是一个处理器类型,终究运用Handle注册。

// src/net/http/server.go
type HandlerFunc func
func  ServeHTTP {
 f
仿制代码

留意,这几个接口和办法名很简单混杂,这儿再着重一下:

一般的 Web 服务器有十分多的 URL 绑定,不同的 URL 对应不同的处理器。可是服务器是怎样决议运用哪个处理器的呢?例如,咱们现在绑定了 3 个 URL,/和/hello和/hello/world。

明显,假如恳求的 URL 为/,则调用/对应的处理器。假如恳求的 URL 为/hello,则调用/hello对应的处理器。假如恳求的 URL 为/hello/world,则调用/hello/world对应的处理器。 可是,假如恳求的是/hello/others,那么运用哪一个处理器呢? 匹配遵从以下规矩:

这儿有一个留意点,假如注册的 URL 不是以/结束的,那么它只能准确匹配恳求的 URL。反之,即便恳求的 URL 只要前缀与被绑定的 URL 相同,ServeMux也以为它们是匹配的。

这也是为什么上面过程进行到/hello/时,不能匹配/hello的原因。由于/hello不以/结束,有必要要准确匹配。 假如,咱们绑定的 URL 为/hello/,那么当服务器找不到与/hello/others彻底匹配的处理器时,就会退而求其次,开端寻觅能够与/hello/匹配的处理器。

看下面的代码:

package main
import  {
 fmt.Fprintf
func helloHandler {
 fmt.Fprintf
func worldHandler {
 fmt.Fprintf
func main {
 mux := http.NewServeMux
 mux.HandleFunc
 mux.HandleFunc
 mux.HandleFunc
 server := http.Server{
 Addr: :8080 ,
 Handler: mux,
 if err := server.ListenAndServe; err != nil {
 log.Fatal
仿制代码

假如注册时,将/hello改为/hello/,那么恳求localhost:8080/hello/和localhost:8080/hello/world/都将回来 This is the hello page 。自己试试吧!

考虑: 运用/hello/注册处理器时,localhost:8080/hello/回来什么?

本文介绍了 Go Web 程序的根本结构。Go Web 的根本形式如下:

package main
import  {
 fmt.Fprintf
type greetingHandler struct {
 Name string
func  ServeHTTP {
 fmt.Fprintf
func main {
 mux := http.NewServeMux
 // 注册处理器函数
 mux.HandleFunc
 // 注册处理器
 mux.Handle
 server := http.Server {
 Addr: :8080 ,
 Handler: mux,
 if err := server.ListenAndServe; err != nil {
 log.Fatal
仿制代码

后续文章中大部分程序仅仅在此基础上添加处理器或处理器函数并注册到相应的 URL 中罢了。处理器和处理器函数能够只运用一种或两者都运用。留意,为了便利,命名中我都加上了Handler。