当前位置 : 主页 > 网络编程 > PHP >

Go 语言处理 Web 请求

来源:互联网 收集:自由互联 发布时间:2023-09-06
在 Go 语言中, ​ ​Handle​ ​​ 是专门用于处理 Web 请求的。当有一个 HTTP 请求时,Go 语言会创建一个 ​ ​goroutine​ ​​ ,请求的过程由创建的这个 goroutine 完成。在 Go 中,有 ​

在 Go 语言中, ​​Handle​​​ 是专门用于处理 Web 请求的。当有一个 HTTP 请求时,Go 语言会创建一个 ​​goroutine​​​ ,请求的过程由创建的这个 goroutine 完成。在 Go 中,有 ​​http.DefaulServeMux​​ 专门用来处理这个过程。


Go 语言处理 Web 请求_网络地址

创建 Web Server

Go 语言处理 Web 请求_网络接口_02


创建 Web Server 有两种方法:

  • 使用 ​​http.ListenAndServer()​​ 创建 Web Server ,该函数有两个参数,第一个参数是网络地址,第二个参数是 handler 。
  • 创建 ​​http.Server​​ 结构体,调用 ​​server.ListenAndServe()​​ 创建 Web Server ,使用该方法可以灵活配置。

首先介绍第一种方法,使用 ​​http.ListenAndServer()​​​ 函数。该函数的第一个参数是网络地址,如果为 ​​""​​​ ,那么就是所有网络接口的 80 端口。第二个参数是 handler ,如果为 ​​nil​​​ ,就是 ​​DefaultServeMux​​ 。DefaultServeMux 在 Go 语言中是一个 multiplexer ,可以看作路由器。

接下来我们使用 ​​http.ListenAndServe()​​ 函数创建一个 Web Server :

package main

import (
"net/http"
)

func main() {
http.ListenAndServe(":8080", nil)
}

运行该程序,打开浏览器,访问 ​​http://localhost:8080/​​​ ,会出现显示 ​​404 page not found​​ 的网页。因为这里我们还没有针对特定的路由编写对应处理的代码。

查看源代码可以看到 ​​ListenAndServe()​​ 函数:

func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}

它创建了一个 ​​Server​​​ , ​​http.Server​​​ 是一个结构体, ​​Addr​​​ 字段表示网络地址,如果为 ​​""​​​ ,那么就是所有网络接口的 80 端口。​​Handler​​​ 字段,如果为 ​​nil​​​ ,那么就是 ​​DefaultServeMux​​​ 。​​DefaultServeMux​​​ 是一个 multiplexer ,也是一个 ​​Handler​​​ ,用于转交给其他 Handler 请求。最后再由 Server 调用 ​​ListenAndServe()​​ 函数创建 Web Server ,这个函数没有参数:

func (srv *Server) ListenAndServe() error {
if srv.shuttingDown() {
return ErrServerClosed
}
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(ln)
}

了解了 ​​http.ListenAndServer()​​​ 创建 Web Server 的原理后,我们可以使用创建 ​​http.Server​​​ 结构体的方法,把上面的例子改成使用 ​​http.Server​​ 来实现相同的功能:

package main

import (
"net/http"
)

func main() {
server := http.Server{
Addr: "localhost:8080",
Handler: nil,
}
server.ListenAndServe()
}

Go 语言处理 Web 请求_网络地址

单个 Handler 处理请求

Go 语言处理 Web 请求_网络接口_02


使用 Handle 处理请求有两个方法:

  • 使用 ​​http.Handle()​​ 函数,第二个参数是 Handler
  • 使用 ​​http.HandleFunc()​​ 函数,第二个参数是 Handler 函数

​handler​​​ 是一个接口(interface), handler 定义了一个方法 ​​ServeHTTP()​​ ,该方法有两个参数,第一个参数是 ResponseWriter ,第二个参数是指向 Request 结构体的指针。

type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

下面我们自己做一个 Handler 用于处理 Web 请求:

package main

import (
"net/http"
)

type myHandler struct {}

func (handler *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World"))
}

func main() {
handler := myHandler{}
server := http.Server{
Addr: "localhost:8080",
Handler: &handler,
}
server.ListenAndServe()
}

运行该程序,打开浏览器,访问 ​​http://localhost:8080/​​​ ,会出现显示 ​​Hello World​​​ 的网页。我们换一个地址 ​​http://localhost:8080/hello​​​ 出现的还是显示 ​​Hello World​​​ 的网页。这里所有请求的地址都会使用这个 Handler 处理请求,把 ​​Hello World​​ 输出。


Go 语言处理 Web 请求_网络地址

多个 Handler 处理请求

Go 语言处理 Web 请求_网络接口_02


要使用多个 Handler 处理请求,就不能指定 ​​Server struct​​​ 里面的 Handler 字段值,使用 ​​nil​​​ ,就是默认的 ​​DefaultServeMux​​​ 。然后我们可以使用 ​​http.Handle​​​ 将某个 Handler 附加到 ​​DefaultServeMux​​ 。

下面来看 ​​http.Handle​​ ,第一个参数表示 URL 后面跟的路径,第二个参数是 handler :

func Handle(pattern string, handler Handler)

接下来我们继续修改,创建两个 Handler ,分别是 ​​aHandler​​​ 和 ​​bHandler​​​ 。然后,再使用 ​​http.Handle()​​​ 函数绑定路径 ​​/a​​​ 对应的是 ​​aHandler​​​ ,路径 ​​/b​​​ 对应的是 ​​bhandler​​ 。

package main

import (
"net/http"
)

type aHandler struct {}

func (handler *aHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("AAA"))
}

type bHandler struct {}

func (handler *bHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("BBB"))
}

func main() {
ahandler := aHandler{}
bhandler := bHandler{}
server := http.Server{
Addr: "localhost:8080",
Handler: nil,
}
http.Handle("/a", &ahandler)
http.Handle("/b", &bhandler)
server.ListenAndServe()
}

运行该程序,打开浏览器,访问 ​​http://localhost:8080/​​​ ,会出现显示 ​​404 page not found​​​ 的网页。我们访问地址 ​​http://localhost:8080/a​​​ 出现的是显示 ​​AAA​​​ 的网页。再访问地址 ​​http://localhost:8080/b​​​ 出现的是显示 ​​BBB​​ 的网页。这样我们就实现了在多个 Handler 里面每个 Handler 对应不同的路径,对应不同的处理方法。

讲完了使用 ​​http.Handle()​​​ 函数处理请求,接下来我们讲讲使用 ​​http.HandleFunc()​​​ 函数处理多个请求。​​http.HandleFunc()​​ 函数定义如下:

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

接下来我们修改代码,添加两个函数:

package main

import (
"net/http"
)

func d(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("DDD"))
}

func e(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("EEE"))
}

func main() {
server := http.Server{
Addr: "localhost:8080",
Handler: nil,
}
http.HandleFunc("/c", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("CCC"))
})
http.HandleFunc("/d", d)
// http.HandlerFunc(e) 是类型转换
// 把 Handler 函数转化为 Handler
// 内部调用的还是 http.Handle 函数
http.Handle("/e", http.HandlerFunc(e))
server.ListenAndServe()
}

Go 有一个 ​​HandlerFunc​​​ 的函数类型。可以将某个具有适当签名的函数 f ,适配成为一个 ​​Handler​​​ ,而这个 ​​Handler​​ 具有方法 f :

type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)

运行该程序,打开浏览器,访问 ​​http://localhost:8080/c​​​ 出现的是显示 ​​CCC​​​ 的网页。再访问地址 ​​http://localhost:8080/d​​​ 出现的是显示 ​​DDD​​​ 的网页,再访问地址 ​​http://localhost:8080/e​​​ 出现的是显示 ​​EEE​​ 的网页。




上一篇:Go 语言系列37:反射
下一篇:没有了
网友评论