本项目源码
简介
- 本系列将从 Gin 的第一次 git 提交 15216a0 出发,简洁化地将 Gin 的代码进行提取,方便学习以及深入了解 Gin 这个框架
须知
- Gin 的核心路由使用了 httprouter 包
基础 struct
- Gin 中将请求,响应等,都进行了 struct 包装
响应 struct
// 核心响应 struct
// Writer 对 http.ResponseWriter 进行了封装,用以响应数据
// Error 包含了错误信息的收集与存储
// Params httprouter 包中,请求路由的参数
// handlers 中间件实现的关键,本质上是另一个 Content
// index 中间件实现的关键,表示进行到的层次
// engine 服务运行基础引擎
type Content struct {
Req *http.Request
Writer ResponseWriter
Error []ErrorMsg
Params httprouter.Params
handlers []HandlerFunc
engine *Engine
index int8
}
// 错误信息结构体
type ErrorMsg struct {
Message string `json:"msg"` // 信息
Meta interface{} `json:"meta"` // 元信息
}
// interface 多元化响应信息
type ResponseWriter interface {
http.ResponseWriter
Status() int
Written() bool
}
// 请求处理
type HandlerFunc func(*Content)
引擎 struct
// Engine 引擎
// RouterGroup 路由组!
// router httprouter包的实例
type Engine struct {
*RouterGroup
router *httprouter.Router
}
// RouterGroup 路由组
type RouterGroup struct {
Handlers []HandlerFunc
prefix string
parent *RouterGroup
engine *Engine
}
武装 struct
- 在基本 stuct 设计完成后,就是要进行方法的增加了
响应
// 写入 Header
func (rw *responseWriter) WriteHeader(s int) {
rw.ResponseWriter.WriteHeader(s)
rw.status = s
}
// 书写返回数据
func (rw *responseWriter) Write(b []byte) (int, error) {
return rw.ResponseWriter.Write(b)
}
// 获取返回状态
func (rw *responseWriter) Status() int {
return rw.status
}
// 是否完成返回值书写
func (rw *responseWriter) Written() bool {
return rw.status != 0
}
请求处理
// 获取父路由组可能有的 请求处理(Handle)
func (group *RouterGroup) allHandlers(handlers []HandlerFunc) []HandlerFunc {
local := append(group.Handlers, handlers...)
if group.parent != nil {
return group.parent.allHandlers(local)
} else {
return local
}
}
// for 循环处理每一层的 Handle
func (c *Content) Next() {
c.index++
s := int8(len(c.handlers))
for ; c.index < s; c.index++ {
c.handlers[c.index](c)
}
}
// 最基本的响应添加
func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) {
p = path.Join(group.prefix, p)
handlers = group.allHandlers(handlers)
group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
group.createContext(w, req, params, handlers).Next()
})
}
// 创建响应 struct
func (group *RouterGroup) createContext(w http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Content {
return &Content{
Req: req,
Writer: &responseWriter{w, 0},
index: -1,
engine: group.engine,
Params: params,
handlers: handlers,
}
}
// Handle 封装
func (group *RouterGroup) GET(path string, handlers ...HandlerFunc) {
group.Handle("GET", path, handlers)
}
// 返回数据格式封装
func (c *Content) String(code int, msg string) {
c.Writer.Header().Set("Content-Type", "text/plain")
c.Writer.WriteHeader(code)
c.Writer.Write([]byte(msg))
}
引擎启动
- 将启动方法进行封装
// 创建引擎
func New() *Engine {
engine := &Engine{}
engine.RouterGroup = &RouterGroup{nil, "/", nil, engine}
engine.router = httprouter.New()
return engine
}
// 默认引擎
func Default() *Engine {
engine := New()
return engine
}
// http 响应接口实现
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
engine.router.ServeHTTP(w, req)
}
// 服务启动!
func (engine *Engine) Run(addr string) {
err := http.ListenAndServe(addr, engine)
if err != nil {
fmt.Println(err)
}
}
基础测试
func main() {
r := gin_copy.Default()
r.GET("/ping", func(c * gin_copy.Content) {
c.String(200, "pong")
})
r.Run(":8082")
}
本文作者: 柠檬炸裂
本文链接: https://www.datamac.cn/archives/gin基础核心源码一
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!