【Golang | Web】中间件的使用

前提概要

承接上一回【Golang | Web】构建Web服务器,我们实现了一个简易的应用HelloWorld,通过监听本地8080端口,提供web服务。客户端通过访问http://127.0.0.1:8080/可以获取返回值 “Hello World!”

故事背景

现在服务端想要统计每次响应请求消耗的时间(这里只涉及app处理请求消耗的时间,不包含链路通信等其他时间),我们可以对HelloWorld作如下简单修改

func HelloWorld(w http.ResponseWriter, r *http.Request) {
	timeStart := time.Now()
	_, err := fmt.Fprintf(w, "Hello World!")
	if err != nil {
		log.Panic(err)
	}
	timeElapse := time.Since(timeStart)
	log.Println(timeElapse)
}

现在如果有第二个,第三个应用,我们也可以进行简单的代码添加。但如果应用很多,30个、100个,这种方法显然就不行了。问题的关键就在于业务代码和非业务代码(时间统计)夹杂在一起了

中间件的引入

思路很简单,就是服务器将获取到的request请求先传递给时间统计的中间件timeMiddleware,然后再由中间件传递给应用HelloWorld,下面是timeMiddleware简单的实现

func timeMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		timeStart := time.Now()
		//传递参数给下一个http.Handler
		next.ServeHTTP(w, r)
		timeElapse := time.Since(timeStart)
		log.Println(timeElapse)
	})
}

在main函数中开启监听

func main() {
	http.Handle("/", timeMiddleware(http.HandlerFunc(HelloWorld)))
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Panic(err)
	}
}

这里需要补充说明http.Handler、http.HandlerFunc、ServeHttp之间的关系

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

type HandlerFunc func(ResponseWriter, *Request)

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}

Handler是一个接口,只有一个方法ServeHttp,HandlerFunc是一个函数类型,实现了Handler接口,所以在timeMiddleware中通过调用next.ServeHTTP(w, r) 就是在传递参数执行app

现在拓展一下,如果要继续添加一个log功能,我们可以这么实现

//新增一个中间件用于log的生成
func logMiddleware(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		file, _ := os.OpenFile("test.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
		logger := log.New(file, "", log.Llongfile|log.LstdFlags)
		//将w,r传递给下一个handler
		h.ServeHTTP(w, r)
		logger.Println("请求处理完成")
	})
}
func main() {
	http.Handle("/", logMiddleware(timeMiddleware(http.HandlerFunc(HelloWorld))))
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Panic(err)
	}
}

通过浏览器访问后,后台可以获取如下的log信息:
2022/04/16 19:32:07 E:/goland-workspace/goRestful/httptest/main.go:38: 请求处理完成
2022/04/16 19:32:07 E:/goland-workspace/goRestful/httptest/main.go:38: 请求处理完成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Golang是一种强大的编程语言,非常适合构建Web应用程序。虽然有很多流行的Web框架可以帮助我们快速地建立和开发Web应用程序,但有时候可能会选择不使用框架来构建一个GolangWeb应用程序。 首先,不使用框架可以提高对Golang语言本身的了解和熟练程度。通过不使用框架,我们需要直接使用Golang的标准库来处理网络请求、路由、中间件等功能。这样可以更深入地了解Golang的并发性能、内存管理和其他底层机制,从而提高自己的编程技巧和能力。 其次,不使用框架可以更好地满足特定的需求。有时候我们可能会遇到一些特殊的需求,需要定制化的功能或性能优化。在这种情况下,使用框架可能会受到限制,而不使用框架可以让我们有更多的自由来实现自己的解决方案。 此外,不使用框架可以避免框架带来的额外复杂性和依赖性。使用框架可能需要我们学习和适应框架的规范和设计模式,也会导致我们的应用程序依赖于框架的版本和更新。而不使用框架可以减少这些额外的复杂性和依赖性,使我们的应用程序更容易维护和扩展。 当然,不使用框架也意味着我们需要更多地编写自己的代码,更多地处理底层的细节。这需要我们具备更高的技术水平和更大的耐心。但对于经验丰富的开发人员或有特定需求的项目来说,不使用框架可能是一个值得考虑的选择。 总之,不使用框架可以帮助我们提高对Golang语言本身的了解和熟练程度,满足特定的需求,减少复杂性和依赖性。但这需要我们具备更高的技术水平和耐心。在确定选择之前,需要权衡利弊并根据具体情况做出决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

田土豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值