首页 > 其他分享 >Mygin实现上下文

Mygin实现上下文

时间:2024-01-17 14:15:43浏览次数:27  
标签:http string 实现 Mygin func Context return 上下文 method

本篇是Mygin的第三篇

目的

  • 将路由独立出来,方便后续扩展修改
  • 上下文Context,对http.ResponseWriter和http.Request进行封装,实现对JSON、HTML等的支持

路由

新建一个router文件,将 Mygin实现简单的路由 中将路由部分复制出来

  • 新建Mygin/router.go
package mygin

import (
	"log"
	"net/http"
)

// 路由节点
type methodTree struct {
	method string
	paths  map[string]func(c *Context)
}

type methodTrees map[string]methodTree

type Router struct {
	trees methodTrees
}

// 获取路由root根
func (r *Router) getRoot(method string) methodTree {
	if root, ok := r.trees[method]; ok {
		return root
	}
	r.trees[method] = methodTree{method: method, paths: make(map[string]func(c *Context))}
	return r.trees[method]
}

// 添加路由方法
func (r *Router) addRoute(method, path string, ctx func(c *Context)) {
	root := r.getRoot(method)

	if _, ok := root.paths[path]; ok {
		log.Default().Println(path, "is exist")
		return
	}

	root.method = method
	root.paths[path] = ctx

}

// Get Get方法
func (r *Router) Get(path string, handler func(c *Context)) {
	r.addRoute(http.MethodGet, path, handler)
}

// Post  Post方法
func (e *Engine) Post(path string, handler func(c *Context)) {
	e.addRoute(http.MethodPost, path, handler)
}

  • 修改Mygin/engine.go文件
package mygin

import (
	"net/http"
)

type Engine struct {
	Router
}

func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	if tree, ok := e.trees[r.Method]; ok {
		if handler, ok := tree.paths[r.URL.Path]; ok {
			handler(w, r)
			return
		}
	}
	w.Write([]byte("404 Not found!\n"))
}

// Default returns an Engine
func Default() *Engine {
	return &Engine{
		Router{
			trees: make(methodTrees, 2),
		}}
}

// Run 启动方法start a http server
func (e *Engine) Run(addr string) {
	err := http.ListenAndServe(addr, e)
	if err != nil {
		return
	}
}
  • 相当于engine继承router,engine可以调用router中的方法。

上下文

对于1个请求来说,无法就是接收http.Request的数据处理,然后将处理后的数据http.ResponseWriter返回。虽然响应的消息体(Body)不一样,但对于同一种类型比如JSON类型,消息头(Header)和消息体(Body),而 Header 包含了状态码(StatusCode),消息类型(ContentType)等几乎每次请求都需要重新写,所以进行封装,对于后续扩展和修改都非常必要。

  • 新建mygin/context.go文件
package mygin

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

type Context struct {
	Request *http.Request
	Writer  http.ResponseWriter
}

func writeContentType(w http.ResponseWriter, value []string) {
	header := w.Header()
	if val := header["Content-Type"]; len(val) == 0 {
		header["Content-Type"] = value
	}

}

func (c *Context) Status(code int) {
	c.Writer.WriteHeader(code)
}

func (c *Context) JSON(v interface{}) error {
	writeContentType(c.Writer, []string{"application/json; charset=utf-8"})
	encoder := json.NewEncoder(c.Writer)
	err := encoder.Encode(v)
	if err != nil {
		c.Status(http.StatusInternalServerError)
	}
	c.Status(http.StatusOK)
	return err
}

func (c *Context) Html(v string) error {
	writeContentType(c.Writer, []string{"text/html; charset=utf-8"})
	c.Status(http.StatusOK)
	_, err := c.Writer.Write([]byte(v))
	return err
}

func (c *Context) String(v string) error {
	writeContentType(c.Writer, []string{"text/plain; charset=utf-8"})
	c.Status(http.StatusOK)
	_, err := c.Writer.Write([]byte(v))
	return err
}

  • 在context中实现了JSON、Html、String方法

main.go文件修改

package main

import (
	"gophp/mygin"
)

func main() {
	engine := mygin.Default()
	engine.Get("/json", func(c *mygin.Context) {
		c.JSON(map[string]interface{}{
			"name":     "zs",
			"password": "1234",
		})
	})

	engine.Get("/html", func(c *mygin.Context) {
		c.Html("<h1>hello html!</h1>")
	})

	engine.Get("/string", func(c *mygin.Context) {
		c.String("string...")
	})

	engine.Run(":9501")
}

接下来看实际效果

curl -i http://localhost:9501/json
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 17 Jan 2024 05:52:28 GMT
Content-Length: 32

{"name":"zs","password":"1234"}

 ~ curl -i http://localhost:9501/html
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Date: Wed, 17 Jan 2024 05:52:36 GMT
Content-Length: 20

<h1>hello html!</h1>                                                                                                  

~ curl -i http://localhost:9501/string
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Wed, 17 Jan 2024 05:52:42 GMT
Content-Length: 9

string...

标签:http,string,实现,Mygin,func,Context,return,上下文,method
From: https://www.cnblogs.com/pengb/p/17969328

相关文章

  • Python实现AI换脸功能
    运行时如果提示模块requests和simplejson不存在使用命令pipinstallrequestspipinstallsimplejsonimportrequestsimportjsonimportsimplejsonimportbase64#第一步:获取人脸关键点deffind_face(imgpath):""":paramimgpath:图片的地址:return:......
  • CH395实现MQTT应用(补充说明)
    本文是对该篇文章的补充CH395+EMQX实现MQTT应用(Windows系统)-lqlq123-博客园(cnblogs.com)1.切换中文版在设置中可以选择EMQX使用语言及样式主题 2.监控主题及消息数据第一种方法:点击左侧监控,下拉可以直接看到所有客户端的数据详情第二种方法:想要监控特......
  • SpringBoot中整合MybatisPlus快速实现Mysql增删改查和条件构造器
    场景Mybatis-Plus(简称MP)是一个Mybatis的增强工具,只是在Mybatis的基础上做了增强却不做改变,MyBatis-Plus支持所有Mybatis原生的特性,所以引入Mybatis-Plus不会对现有的Mybatis构架产生任何影响。MyBatis增强工具包,简化CRUD操作。启动加载XML配置时注入单表SQL操作,为简......
  • js实现快速排序和归并排序
    letarr1=[8,3,9,14,32,2,1,5]//归并排序functionmergeSort(arr){if(arr.length<2)returnarrletmid=Math.floor(arr.length/2)letleft=arr.slice(0,mid)letright=arr.slice(mid)returnmerge(mergeSort(left),merg......
  • 基于SpringBoot+Vue的校园招聘系统设计实现(源码+lw+部署文档+讲解等)
    (文章目录)前言:heartpulse:博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌:heartpulse:......
  • python实现抓取表情网站图片
    1:效果图2:代码importosimportrequestsfrombs4importBeautifulSoupifnotos.path.exists('./images/'):os.mkdir('./images/')headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(K......
  • SpringBoot使用jwt实现接口带令牌访问
    1、 添加依赖<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>${jwt.version}</version></dependency>2、先定义一个用户实体@Data@TableName("t_user")publicclass......
  • 如何阅读芯片手册,裸机驱动开发步骤以及纯汇编实现点灯,汇编结合c点灯,c实现点灯
    一.如何阅读芯片手册(datasheet)     作为嵌入式学习者,如何去阅读芯片手册是重中之重。不管是什么芯片手册,在写的怎么天花乱坠,它的本质也就是使用说明书。     可是问题来了,它Y的是本英语的说明书,但是英语不好的友友们不要过于焦虑,我们现在有了很好的翻译软件......
  • 通过Power BI实现数据的实时刷新与展示2-使用Python Code无限实时刷新数据源
    上一篇讲了使用DirectQueryMode来实现数据自动刷新,但是DirectMode只能适用于Database这种数据源,很多其它的源都不行。对于其它类型的数据源,就只能另想办法了。PBI刷新可以用以下2种方式:1,在PBIDesktop中点击刷新,然后刷新完成后,再Publish2,将报告发布到WorkSpace中,然后在选中D......
  • Android gradle dependency tree change(依赖树变化)监控实现,sdk version 变化一目了然
    @目录前言基本原理执行流程diff报告不同分支merge过来的diff报告同个分支产生的merge报告同个分支提交的diff报告具体实现原理我们需要监控怎样的Dendenpency变化怎样获取dependencyTreeproject.configurations方式./gradlewdependenciesAsciiDependencyReportRe......