学习Go语言Web框架Gee总结--上下文Context(二)

发布时间:2024年01月02日

学习网站来源:Gee

项目目录结构:
在这里插入图片描述

context/go.mod

module example

go 1.21.5

require gee v0.0.0
replace gee => ./gee

context/main.go

package main

import (
	"gee"
	"net/http"
)

func main() {
	r := gee.New()
	//http.StatusOK为常量200
		c.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 gee

import (
	"encoding/json"
	"fmt"
	"net/http"
)

type H map[string]interface{}

//自定义的Context结构体是一个用于在处理 HTTP 请求时封装请求上下文信息的工具,它简化了处理请求和返回响应的过程,提供了更加友好和便利的接口
type Context struct {
	Writer     http.ResponseWriter
	Req        *http.Request
	Path       string
	Method     string
	StatusCode 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 = code
	c.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 gee

import (
	"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 + "-" + pattern
	r.handlers[key] = handler
}

func (r *router) handle(c *Context) {
	key := c.Method + "-" + c.Path
	if 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 gee

import "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)
}

文章来源:https://blog.csdn.net/2301_78179333/article/details/135338673
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。