【Go】 HTTP编程3-路由httprouter

 HttpRouter

httprouter

  • httprouter是第三方的库,不是go的标准库,使用命令 go get -u github.com/julienschmidt/httprouter ,下载该模块,-u表示如果已经下载但更新到最新版本
  • Router 实现了http.Handler接口,为各种 request method (get/post等) 提供了便捷的路由方式,之前是根据路径区分,现在可以根据方法区分
  • 支持restful请求方式,什么是restful ,原来参数通过?参数名=参数值 进行参数传递, 现在可以把参数放到路径中 ,但是需要提前约定好每一集路径代表什么参数
  • 支持ServeFiles访问静态文件,现实中 ,服务端多的是需要返回HTML页面,html页面怎么返回,在第三方包中可以把静态文件返回给客户端 
  • 可以自定义处理panic的方法

HttpRouter 是一个轻量级高性能的 HTTP 请求路由器(也称为多路复用器或简称 mux)用于 Go 语言。

与 Go 的 net/http 包中默认的 mux 不同,该路由器支持路由模式中的变量,并且匹配请求方法。它还具有更好的扩展性。

该路由器经过优化,具有高性能和小内存占用。即使在非常长的路径和大量路由的情况下,它也能很好地扩展。采用了一种压缩动态字典树(基数树)结构以实现高效匹配。

特点

仅显式匹配:与其他路由器(如 http.ServeMux)不同,请求的 URL 路径可能与多个模式匹配。因此它们具有一些尴尬的模式优先规则,如最长匹配或首次注册,首次匹配。通过该路由器的设计,一个请求只能匹配一个或零个路由。因此,也不会出现意外的匹配,这使其非常适合 SEO 并提高了用户体验。

不必再关心尾部斜杠:选择你喜欢的 URL 样式,如果缺少尾部斜杠或有一个额外的,路由器会自动将客户端重定向。当然,它只会这样做,如果新路径有一个处理程序。如果你不喜欢,可以关闭此行为。

路径自动修正:除了在不增加额外成本的情况下检测缺少或额外的尾部斜杠外,路由器还可以修复错误的情况并删除多余的路径元素(如 ../ 或 //)。是否有使用大写锁定键的用户?HttpRouter 可以通过进行大小写不敏感的查找并将其重定向到正确的 URL 来帮助他。

路由模式中的参数:停止解析请求的 URL 路径,只需给路径段一个名称,路由器就会将动态值传递给您。由于路由器的设计,路径参数非常便宜。

零垃圾:匹配和分派过程不会生成任何垃圾字节。唯一的堆分配是构建路径参数的键值对切片以及构建新的上下文和请求对象(后者仅在标准 Handler/HandlerFunc API 中)。在 3 参数 API 中,如果请求路径不包含任何参数,则不需要进行任何堆分配。

最佳性能:基准测试说话。请参阅下面有关实现的技术细节。

不再有服务器崩溃:您可以设置 Panic 处理程序来处理在处理 HTTP 请求期间发生的 panic。然后路由器会恢复并让 PanicHandler 记录发生的情况并提供一个友好的错误页面。

非常适合 API:路由器设计鼓励构建合理的、分层的 RESTful API。此外,它还内置了对 OPTIONS 请求和 405 Method Not Allowed 回复的本地支持。

当然,您也可以设置自定义的 NotFound 和 MethodNotAllowed 处理程序,并提供静态文件服务。

使用

下载库

$ go get github.com/julienschmidt/httprouter

package main

import (
	"fmt"
	"github.com/julienschmidt/httprouter"
	"net/http"
)


// 接受的参数 w http.ResponseWriter,r *http.Request, params httprouter.Params
func get(w http.ResponseWriter,r *http.Request, params httprouter.Params)  {
	// 打印请求方法
	fmt.Printf("request method:%s",r.Method)

	// 打印请求体
	fmt.Println("request Body:")
	//io.Copy(os.Stdout,r.Body)

	// 打印请求头
	fmt.Println("request Header:")
	for k,v := range r.Header {
		fmt.Printf("%s = %s\n", k,v)
	}

	// 返回客户端的内容,下面两种方式等价
	fmt.Fprintf(w,"hello boy!")
	//w.Write([]byte("hello boy!"))

}

func panicTest(w http.ResponseWriter,r *http.Request, params httprouter.Params)  {
	// 打印请求方法
	fmt.Printf("request method:%s",r.Method)

	// 打印请求体
	fmt.Println("request Body:")
	//io.Copy(os.Stdout,r.Body)

	// 打印请求头
	fmt.Println("request Header:")
	for k,v := range r.Header {
		fmt.Printf("%s = %s\n", k,v)
	}

	// 返回客户端的内容,下面两种方式等价
	fmt.Fprintf(w,"hello boy!")
	//w.Write([]byte("hello boy!"))

	// 故意制造一个数组越界 panic

	arr := [5]int{1, 2, 3, 4, 5}
	for i := 0; i < 10; i++ {
		fmt.Println(arr[i])
	}

}


func post(w http.ResponseWriter,r *http.Request,params httprouter.Params)  {
	// 打印请求方法
	fmt.Printf("request method:%s\n",r.Method)
	// 打印请求体
	fmt.Println("request Body:")
	//io.Copy(os.Stdout,r.Body)

	// 打印请求头
	fmt.Println("request Header:")
	for k,v := range r.Header {
		fmt.Printf("%s = %s\n", k,v)
	}

	// 返回客户端的内容,下面两种方式等价
	fmt.Fprintf(w,"hello girl!")
	//w.Write([]byte("hello boy!"))
}

func main ()  {
	router := httprouter.New()
	// GET is a shortcut for router.Handle(http.MethodGet, path, handle)
	// GET 是  router.Handle(http.MethodGet, path, handle)  简写
	// GET 接收两个参数,第一个参数 字符串类型 代表请求路径,第二个参数是函数类型  func(http.ResponseWriter, *http.Request, Params),代表处理函数,所以我们在写处理函数的时候,需要满足这个类型
	router.GET("/",get)
	router.GET("/panictest",panicTest)
	// restful 风格
	router.GET("/user/:name/:type/*addr", func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
		fmt.Printf("name= %s,type=%s addr = %s",params.ByName("name"),params.ByName("type"),params.ByName("addr"))
		msg :=fmt.Sprintf("name= %s,type=%s addr = %s",params.ByName("name"),params.ByName("type"),params.ByName("addr"))
		writer.Write([]byte(msg))
	})

	// ServerFiles - 返回静态文件 ,访问 http://127.0.0.1:8888/file/a.html路径 ,会去目录 ./static 找 a.html文件
	router.ServeFiles("/file/*filepath",http.Dir("./static"))

	router.PanicHandler = func(writer http.ResponseWriter, request *http.Request,i interface{}) {
		fmt.Fprintf(writer,"服务器正在维护:%s,请稍后再试",i)
	}

	//  ListenAndServe 第一个参数是地址,第二个参数是 实现 handler类型的函数

	http.ListenAndServe(":8888",router)

}

参考资料

GitHub

GitHub - julienschmidt/httprouter: A high performance HTTP request router that scales well

文档

httprouter package - github.com/julienschmidt/httprouter - Go Packages

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DBA之路

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

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

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

打赏作者

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

抵扣说明:

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

余额充值