【Study】Go语言动手写Web框架-Gee第一天
【Study】Go语言动手写Web框架-Gee第一天
项目来源: 7天用Go动手写/从零实现系列
第一天
1. net/http的简易demo
代码和一些说明
1 | |
使用Go语言内置的net/http库, 简单写个demo
第10、11行:设置两个路由,分别是
/和/hello,并且分别绑定了两个函数(第16、20行)indexHandler和helloHandler处理
indexHandler,返回的是URL;处理helloHandler,返回的是请求头内的信息第12行:设置端口为9999,表示在9999端口进行监听。第二个参数为处理所有http请求实例,
nil代表使用标准库中的实例处理。
http.ListenAndServe底层源码:
1
2
3
4
5
6
7
8
9
10
11
12// ListenAndServe listens on the TCP network address addr and then calls
// Serve with handler to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
//
// The handler is typically nil, in which case the DefaultServeMux is used.
//
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
Handler底层源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27// A Handler responds to an HTTP request.
//
// ServeHTTP should write reply headers and data to the ResponseWriter
// and then return. Returning signals that the request is finished; it
// is not valid to use the ResponseWriter or read from the
// Request.Body after or concurrently with the completion of the
// ServeHTTP call.
//
// Depending on the HTTP client software, HTTP protocol version, and
// any intermediaries between the client and the Go server, it may not
// be possible to read from the Request.Body after writing to the
// ResponseWriter. Cautious handlers should read the Request.Body
// first, and then reply.
//
// Except for reading the body, handlers should not modify the
// provided Request.
//
// If ServeHTTP panics, the server (the caller of ServeHTTP) assumes
// that the effect of the panic was isolated to the active request.
// It recovers the panic, logs a stack trace to the server error log,
// and either closes the network connection or sends an HTTP/2
// RST_STREAM, depending on the HTTP protocol. To abort a handler so
// the client sees an interrupted response but the server doesn't log
// an error, panic with the value ErrAbortHandler.
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
http.ListenAndServe()的第二个参数类型可以看到是一个接口,需要实现ServeHTTP方法,也就是说所有HTTP请求都交给它来处理(第二节实现)
log.Fatal(): 进入源码我们可以看到这样的注释Fatal is equivalent to Print() followed by a call to os.Exit(1).可以得知,当程序报错之后打印日志并会立即退出,defer函数也不会执行,而不同于
panic()
panic():
- 函数立刻停止执行 (注意是函数本身,不是应用程序停止)
- defer函数被执行
- 返回给调用者(caller)
- 调用者函数假装也收到了一个panic函数,从而
4.1 立即停止执行当前函数
4.2 它defer函数被执行
4.3 返回给它的调用者(caller)- …(递归重复上述步骤,直到最上层函数)
应用程序停止。
一些运行结果
当然也可以使用curl工具
2. 实现http.Handler接口
需要构造一个对象,并且实现ServeHTTP方法
1 | |
定义
Engine对象,并且实现其中的函数ServeHTTP(http.ResponseWriter, *http.Request),对URL处理只有/个/hello,处理的逻辑同上。函数中的两个参数分别为:针对第二个参数请求的响应,请求的信息。
3. 重新组织代码结构,实现核心功能,准备被调用
使用New()创建 gee 的实例,使用 GET()方法添加路由,最后使用Run()启动Web服务。
1 | |
1 | |
1 | |
1 | |
代码和一些说明
执行
main()函数,首先进行实例化了gee,main.go中的12行开始执行,调用GET()方法时,会到gee.go中addRoute()添加路由和映射例如:r.GET(“/“, handler),则会在映射表中添加{“GET-/“: handler}
main.go中,两个路由/和/hello添加完毕开始执行r.Run(),运行服务。Run()中的ListenAndServe(addr, handler)函数,又会去执行handler中的接口,也就是ServeHTTP(),由于我们在gee.go文件中已经实现了该方法,会进行调用。gee.go文件中,实现了实例化的过程New()函数
一些运行结果