7days gee记录

学习

geektutu

gee 框架

HTTP 基础

核心

1
2
3
http.HandleFunc("/", indexHandler)
http.HandleFunc("/hello", helloHandler)
log.Fatal(http.ListenAndServe(":9999", nil))

通过捆绑路径和 url 类型为 w http.ResponseWriter, req *http.Request

实现方法 ServeHTTP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
type Engine struct{}
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	switch req.URL.Path {
	case "/":
		fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path)
	case "/hello":
		for k, v := range req.Header {
			fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
		}
	default:
		fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
	}
}
func main() {
	engine := new(Engine)
	log.Fatal(http.ListenAndServe(":9999", engine))
}

通过定义 Engine 结构体实现 ServeHTTP 再传入 http.ListenAndServe 第二个参数,ServeHTTP 封装了两个路径

封装 gee 包

 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// HandlerFunc defines the request handler used by gee
type HandlerFunc func(http.ResponseWriter, *http.Request)

// Engine implement the interface of ServeHTTP
type Engine struct {
	router map[string]HandlerFunc
}

// New is the constructor of gee.Engine
func New() *Engine {
	return &Engine{router: make(map[string]HandlerFunc)}
}

func (engine *Engine) addRoute(method string, pattern string, handler HandlerFunc) {
	key := method + "-" + pattern
	engine.router[key] = handler
}

// GET defines the method to add GET request
func (engine *Engine) GET(pattern string, handler HandlerFunc) {
	engine.addRoute("GET", pattern, handler)
}

// POST defines the method to add POST request
func (engine *Engine) POST(pattern string, handler HandlerFunc) {
	engine.addRoute("POST", pattern, handler)
}

// Run defines the method to start a http server
func (engine *Engine) Run(addr string) (err error) {
	return http.ListenAndServe(addr, engine)
}

func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	key := req.Method + "-" + req.URL.Path
	if handler, ok := engine.router[key]; ok {
		handler(w, req)
	} else {
		fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
	}
}

定义结构体时创建一个 router 的 map 将原先 func(w http.ResponseWriter, req *http.Request)放入 HandlerFunc 中 addRoute 将 method + “-” + pattern 构造成 router 的 key,value 为 handler 方法只需要传入 engine.addRoute(“GET”, pattern, handler) 通过 Run 来监听 http.ListenAndServe(addr, engine) ServeHTTP 构造 key := req.Method + “-” + req.URL.Path,判断是否在 router 中

上下文

context

1
2
3
4
r := gee.New()
r.GET("/", func(c *gee.Context) {
		c.HTML(http.StatusOK, "<h1>Hello Gee</h1>")
	})

将 context 作为匿名函数放进 Handler

map[string]interface{}起了一个别名 gee.H,构建 JSON 数据时,可以直接封装

1
2
3
4
c.JSON(http.StatusOK, gee.H{
    "username": c.PostForm("username"),
    "password": c.PostForm("password"),
})

router 将 addrouter 拿出修改为支持动态路由,handle 参数变为 context

gee ServeHTTP 通过 router 的 handle 接管 context

前缀树路由

定义节点

1
2
3
4
5
6
type node struct {
	pattern  string // 待匹配路由,例如 /p/:lang
	part     string // 路由中的一部分,例如 :lang
	children []*node // 子节点,例如 [doc, tutorial, intro]
	isWild   bool // 是否精确匹配,part 含有 : 或 * 时为true
}

trie 重点匹配*和:符号进行动态匹配,第一个匹配成功的节点用于插入,递归每一层如果没有 part 新建一个,匹配到末节点才会成功,所有匹配成功的点用于查找

router handlers 存储每种请求方式,getroute 解析*和:,返回一个 map

context 通过 c.Param(“lang”)获取值

分组

将路径划分为组,需要知道父亲节点

1
2
3
4
5
r := gee.New()
v1 := r.Group("/v1")
v1.GET("/", func(c *gee.Context) {
	c.HTML(http.StatusOK, "<h1>Hello Gee</h1>")
})

gee 将 Engine 作为最顶层的分组,也就是说 Engine 拥有 RouterGroup 所有的能力

中间件

通过调用(*Context).Next()函数,中间件可等待用户自己定义的 Handler 处理结束后,再做一些额外的操作,例如计算本次处理所用时间等 需要注意 next 的执行顺序,按照 handler 为准

gee 定义 Use 函数到 group 可以给全局用也可以单独定义一个 group

最后更新于 05月19日 12点44分, 2026年