学习Go语言Web框架Gee总结--上下文Context
- context/go.mod
- context/main.go
- context/gee/context.go
- context/gee/router.go
- context/gee/gee.go
学习网站来源:Gee
项目目录结构:
context/go.mod
module examplego 1.21.5require gee v0.0.0
replace gee => ./gee
context/main.go
package mainimport ("gee""net/http"
)func main() {r := gee.New()//http.StatusOK为常量200c.HTML(http.StatusOK, "<h1>Hello Gee</h1>")})r.GET("/hello", func(c *gee.Context) {c.String(http.StatusOK, "hello %s, you're at %s\n", c.Query("name"), c.Path)})r.POST("/login", func(c *gee.Context) {c.JSON(http.StatusOK, gee.H{"username": c.PostForm("username"),"password": c.PostForm("password"),})})r.Run(":9999")
}
Handler的参数变成成了gee.Context,提供了查询Query/PostForm参数的功能
/hello?firstname=Jane&lastname=Doe这样一个路由, firstname, lastname即是Querystring parameters, 要获取他们就需要使用Query相关函数.
c.Query("firstname") // Jane
c.Query("lastname") // Doe
对于POST, PUT等这些能够传递参数Body的请求, 要获取其参数, 需要使用PostForm
{"username":wang,"password":123
}
username:= c.PostForm("username")
password:= c.PostForm("password")
效果如下:
对于post请求
context/gee/context.go
package geeimport ("encoding/json""fmt""net/http"
)type H map[string]interface{}//自定义的Context结构体是一个用于在处理 HTTP 请求时封装请求上下文信息的工具,它简化了处理请求和返回响应的过程,提供了更加友好和便利的接口
type Context struct {Writer http.ResponseWriterReq *http.RequestPath stringMethod stringStatusCode int
}func newContext(w http.ResponseWriter, req *http.Request) *Context {return &Context{Writer: w,Req: req,Path: req.URL.Path,Method: req.Method,}
}func (c *Context) PostForm(key string) string {return c.Req.FormValue(key)
}func (c *Context) Query(key string) string {return c.Req.URL.Query().Get(key)
}
//用于设置响应的状态码
func (c *Context) Status(code int) {c.StatusCode = codec.Writer.WriteHeader(code)
}
//用于设置响应头中指定键的值
func (c *Context) SetHeader(key string, value string) {c.Writer.Header().Set(key, value)
}
//用于返回一个字符串格式的响应,设置响应头的 Content-Type 为 text/plain,并将格式化后的字符串写入到响应体中
func (c *Context) String(code int, format string, values ...interface{}) {c.SetHeader("Context-Type", "text/plain")c.Status(code)c.Writer.Write([]byte(fmt.Sprintf(format, values...)))
}
//使用json.NewEncoder将对象编码为JSON格式并写入到响应体中,如果在编码过程中出现错误,会返回 500 状态码
func (c *Context) JSON(code int, obj interface{}) {c.SetHeader("Context-Type", "application/json")c.Status(code)encoder := json.NewEncoder(c.Writer)if err := encoder.Encode(obj); err != nil {http.Error(c.Writer, err.Error(), 500)}
}
//用于返回原始的数据
func (c *Context) Data(code int, data []byte) {c.Status(code)c.Writer.Write(data)
}
//用于返回 HTML 内容,它接受一个状态码和一个 HTML 字符串作为参数
func (c *Context) HTML(code int, html string) {c.SetHeader("Content-Type", "text/html")c.Status(code)c.Writer.Write([]byte(html))
}
关于HTTP中的Context-Type
常见的媒体格式类型如下:
- text/html : HTML格式
- text/plain :纯文本格式
- text/xml : XML格式
- image/gif :gif图片格式
- image/jpeg :jpg图片格式
- image/png:png图片格式
以application开头的媒体格式类型:
- application/xhtml+xml :XHTML格式
- application/xml: XML数据格式
- application/atom+xml :Atom XML聚合格式
- application/json: JSON数据格式
- application/pdf:pdf格式
- application/msword : Word文档格式
- application/octet-stream : 二进制流数据(如常见的文件下载)
- application/x-www-form-urlencoded : 中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
context/gee/router.go
将和路由相关的方法和结构单独提取了出来,放到了一个新的文件中router.go,方便我们下一次对 router 的功能进行增强,例如提供动态路由的支持
package geeimport ("log""net/http"
)type router struct {handlers map[string]HandlerFunc
}func newRouter() *router {return &router{handlers: make(map[string]HandlerFunc),}
}func (r *router) addRoute(method string, pattern string, handler HandlerFunc) {log.Printf("Route %4s - %s", method, pattern)key := method + "-" + patternr.handlers[key] = handler
}func (r *router) handle(c *Context) {key := c.Method + "-" + c.Pathif handler, ok := r.handlers[key]; ok {handler(c)} else {c.String(http.StatusNotFound, "404 NOT FOUND: %s\n", c.Path)}
}
context/gee/gee.go
框架入口
package geeimport "net/http"type HandlerFunc func(*Context)type Engine struct {router *router
}func New() *Engine {return &Engine{router: newRouter()}
}func (engine *Engine) addRoute(method string, pattern string, handler HandlerFunc) {engine.router.addRoute(method, pattern, handler)
}func (engine *Engine) GET(pattern string, handler HandlerFunc) {engine.addRoute("GET", pattern, handler)
}func (engine *Engine) POST(pattern string, handler HandlerFunc) {engine.addRoute("POST", pattern, handler)
}func (engine *Engine) Run(addr string) (err error) {return http.ListenAndServe(":9999", engine)
}func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {c := newContext(w, r)engine.router.handle(c)
}