【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()
函数
一些运行结果
