注:本文已发布超过一年,请注意您所使用工具的相关版本是否适用
序 笔记
代码实现首先我们看一下一个简单的实现模板,然后我们再看看实际上我们常用 web 框架 gin 当中是如何处理请求的
Code1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 // Package chain 职责链模式 // 🌰 假设我们现在有个校园论坛,由于社区规章制度、广告、法律法规的原因需要对用户的发言进行敏感词过滤 // 如果被判定为敏感词,那么这篇帖子将会被封禁 package chain// SensitiveWordFilter 敏感词过滤器,判定是否是敏感词 type SensitiveWordFilter interface { Filter(content string ) bool }
// SensitiveWordFilterChain 职责链 type SensitiveWordFilterChain struct { filters []SensitiveWordFilter }
// AddFilter 添加一个过滤器 func (c *SensitiveWordFilterChain) AddFilter (filter SensitiveWordFilter) { c.filters = append (c.filters, filter) }
// Filter 执行过滤 func (c *SensitiveWordFilterChain) Filter (content string ) bool { for _, filter := range c.filters { // 如果发现敏感直接返回结果 if filter.Filter(content) { return true } } return false }
// AdSensitiveWordFilter 广告 type AdSensitiveWordFilter struct {}
// Filter 实现过滤算法 func (f *AdSensitiveWordFilter) Filter (content string ) bool { // TODO: 实现算法 return false }
// PoliticalWordFilter 政治敏感 type PoliticalWordFilter struct {}
// Filter 实现过滤算法 func (f *PoliticalWordFilter) Filter (content string ) bool { // TODO: 实现算法 return true }
单元测试1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package chainimport ( "testing"
"github.com/stretchr/testify/assert" )
func TestSensitiveWordFilterChain_Filter (t *testing.T) { chain := &SensitiveWordFilterChain{} chain.AddFilter(&AdSensitiveWordFilter{}) assert.Equal(t, false , chain.Filter("test" ))
chain.AddFilter(&PoliticalWordFilter{}) assert.Equal(t, true , chain.Filter("test" )) }
Gin 的中间件实现我们直接看一下 gin Context 的实现,其中 Next() 方法就是主要的执行方法,这里其实就是我们最上面说到的职责链模式的变体,因为它会在每一个处理函数中进行处理,而不是第一个接收到就停止了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 type Context struct { // ... // handlers 是一个包含执行函数的数组 // type HandlersChain []HandlerFunc handlers HandlersChain // index 表示当前执行到哪个位置了 index int8
// ... }
// Next 会按照顺序将一个个中间件执行完毕 // 并且 Next 也可以在中间件中进行调用,达到请求前以及请求后的处理 // Next should be used only inside middleware. // It executes the pending handlers in the chain inside the calling handler. // See example in GitHub. func (c *Context) Next () { c.index++ for c.index < int8 (len (c.handlers)) { c.handlers[c.index](c) c.index++ } }
关注我获取更新猜你喜欢