Golang之httpserver

Golang之httpserver,第1张

基于HTTP构建的网络应用包括两个端,即客户端(Client)和服务端(Server)。两个端的交互行为包括从客户端发出request、服务端接受request进行处理并返回response以及客户端处理response。所以http服务器的工作就在于如何接受来自客户端的request,并向客户端返回respond。
典型的http服务端处理流程:
服务器在接收到请求时,首先会进入路由(router),这是一个Multiplexer,路由的工作在于为这个request找到对应的处理器(handler),处理器对request进行处理,并构建response。GOlang实现的http server同样遵循这样的处理流程

http server实现一
package main

import (
	"fmt"
	"net/http"
)

func indexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "hello world")
}

func main() {
	http.HandleFunc("/", indexHandler)
	http.ListenAndServe(":8000", nil)
}


运行代码之后,在浏览器中打开localhost:8000就可以看到hello world 。这段代码先利用http.HandleFunc在跟路由/ 上注册了一个indexHandler,然后利用http.ListenAndServe开启监听。当有请求过来时,则根据路由执行对应的handler函数。

http server 实现方式之二
package main

import (
    "fmt"
    "net/http"
)

type indexHandler struct {
    content string
}

func (ih *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, ih.content)
}

func main() {
    http.Handle("/", &indexHandler{content: "hello world!"})
    http.ListenAndServe(":8001", nil)
}


发现并没有进入监听状态,可能是端口被占用了
筛选8001端口的进程 netstat -ano |findstr “8001”

强制(/F参数)杀死 pid 为 9088 的所有进程包括子进程(/T参数):

taskkill /T /F /PID 592

再次运行 发现可以了 进入监听状态

Go实现的http服务步骤,首先注册路由,然后创建服务并开启监听即可。下文我们将从注册路由、开启服务、处理请求这几个步骤了解Golang如何实现http服务

注册路由

http.HandleFunc和http.Handle都是用于注册路由,可以发现两者的区别在于第二个参数,前者是一个具有func(w http.ResponseWriter,r *http.Request)签名的函数,而后者是一个结构体,该结构体实现了func(w http.ResponseWriter ,r **http.Requests)签名的方法。
http.HandleFunc和http.Handle的源码如下:`

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}
//HandleFunc registers the handler function  for  the  given  pattern
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    if handler == nil {
        panic("http: nil handler")
    }
    mux.Handle(pattern, HandlerFunc(handler))
}
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    if handler == nil {
        panic("http: nil handler")
    }
    mux.Handle(pattern, HandlerFunc(handler))
}

可以看到这两个函数 最总都由DefaultServeMux调用Handle方法来完成路由的注册。
这里我们遇到两种类型的对象:ServeMux和Handler

Handler

handler是一个接口:

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

Handler接口种声明了名为ServeHTTP的函数签名,也就是说任何结构只要实现了这个ServeHTTP方法,那么这个结构体就是一个Handler对象,其实go的http服务都是基于Handler进行处理,而Handler对象的ServeHTTP方法也正是用以处理request并构建response的核心逻辑所在。

回到上面的HandlerFunc函数,注意一下这行代码:

mux.Handle(pattern,HandleFunc(handler))

可能有人会误认为HandleFunc是一个函数,包装了传入handler函数,返回了一个Handler对象。然而这里HandlerFunc实际上是将handler函数做了一个类型转换,看下HandlerFunc的定义:

type HandlerFunc  func(ResponseWriter,*Request)
//ServeHTTP  call f(w,r)
func(f HandlerFunc) ServerHTTP(w ResponseWriter,r *Request){
   f(w,r)
}

HandlerFunc是一个类型,只不过表示的是一个具有func(ResponseWriter, *Request)签名的函数类型,并且这种类型实现了ServeHTTP方法(在ServeHTTP方法中又调用了自身),也就是说这个函数其实就是一个Handler类型的对象,利用这种类型转换,我们可以将一个handler函数转换为一个Handler对象,而不需要定义一个结构体,再让这个结构体实现ServeHTTP方法

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/995392.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存