跟Gin一块搭建自己的web框架(五)

本文围绕Gin Web框架展开,介绍了扩展其功能的方法。在context结构体中加入Keys字段用于传递变量,实现Set和Get函数进行变量的设置与读取,并通过示例展示了如何使用context传递变量。此外,还新增函数用于在错误时主动中断请求,最后给出了对应代码地址。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继续扩展web框架的功能。

context作为某个请求的上下文,必然就需要承担它最基本的功能:在各个中间件和函数之间传递变量。所以我们在context的结构体定义中加入一个Keys的字段,用来放置上下文的变量。

// Context .
	Context struct {
		Req      *http.Request
		Writer   http.ResponseWriter
		Keys     map[string]interface{}
		Params   httprouter.Params
		handlers []HandlerFunc
		engine   *Engine
		index    int8
	}

然后我们需要一个Set函数用来将中间的变量设置进context中

// Set Sets a new pair key/value just for the specefied context.
// It also lazy initializes the hashmap
func (c *Context) Set(key string, item interface{}) {
	if c.Keys == nil {
		c.Keys = make(map[string]interface{})
	}
	c.Keys[key] = item
}

设置的时候需要判断Keys是否初始化了, 如果没有初始化的话,需要先出示话,这个如果对于单例模式有了解的话,就很好理解,相当于懒汉模式。

设置了变量,在需要读取的时候,通过Get函数从context里边取出对应的变量。

// Get Returns the value for the given key.
// It panics if the value doesn't exist.
func (c *Context) Get(key string) interface{} {
	var ok bool
	var item interface{}
	if c.Keys != nil {
		item, ok = c.Keys[key]
	} else {
		item, ok = nil, false
	}
	if !ok || item == nil {
		log.Panicf("Key %s doesn't exist", key)
	}
	return item
}

那么怎么使用context来传递变量呢,还是用上一篇的例子。

我们修改一下,在定义路由的时候,采用路由变量的方式传递一个name变量进去

v1 := r.Group("/v1")
	{
		v1.GET("/login/:name", v1IndexLoginfunc)
	}

在对应的handler中,从Params中取出name变量,然后将这个变量写入到context

func v1IndexLoginfunc(c *gin.Context) {
	name := c.Params.ByName("name")
	c.Set("innerName", name)
	message := getInfo(c)
	c.String(200, message)
}

假设getInfo函数能够通过name获取对应的用户信息,例子中只是简单的返回了一个字符串。

func getInfo(c *gin.Context) string {
	name := c.Get("innerName")
	message := "welcome " + name.(string) // 前提是知道这个是string类型
	return message
}

将web框架启动之后,访问http://localhost:8080/v1/login/harleylau, 会在浏览器显示 “welcome harleylau” ,说明name变量成功的通过context传递到了getInfo函数中。

此外,为了能够在发生错误的时候,主动的中断请求, 在context中新增了几个函数用来主动的退出。

// Abort .
func (c *Context) Abort(code int) {
	c.Writer.WriteHeader(code)
	c.index = AbortIndex
}

// Fail .
func (c *Context) Fail(code int, err error) {
	c.Error(err, "Operation aborted")
	c.Abort(code)
}

func (c *Context) Error(err error, meta interface{}) {
	c.Errors = append(c.Errors, ErrorMsg{
		Message: err.Error(),
		Meta:    meta,
	})
}

对应的代码地址: https://github.com/harleylau/myGin/tree/master/v0.3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值