go-zero的路由机制解析

构建web服务

参考官方教程go-zero安装

//安装goctl插件
go install github.com/zeromicro/go-zero/tools/goctl@latest

//加载go-zero依赖
go get -u github.com/zeromicro/go-zero@latest

zero构建一个http服务器,基于goctl命令创建:

goctl api new demo

在这里插入图片描述

在目录下生成一个web服务

go-zero的路由机制解析_第1张图片
在web目录下,etc是web服务的整体配置,一般包括项目名称,主机,端口等;internal是一个web的主体部分,包括路由,接口配置,逻辑部分,参数类型等;web.api是生成web服务的配置文件和grpc远程服务proto文件生成rpc服务器一样,web.api文件是生成控制器也叫接口的配置文件;web.go文件web服务的入口文件,服务器通过改文件启动。

go-zero的路由机制解析_第2张图片
在internal文件夹下,包含配置文件,控制器,逻辑部分,参数集等。需要加入自己的逻辑部分只需要修改logic目录下的文件即可。

根据官网的提示在logic.go文件27行添加如下代码:
go-zero的路由机制解析_第3张图片

resp = new(types.Response)
resp.Message = req.Name

切换到web目录下,运行web程序
在这里插入图片描述

浏览器输入http://127.0.0.1:8888/from/me

go-zero的路由机制解析_第4张图片
上述步骤实现了基于go-zero的web服务,这个web是基于go的net/http重构的,可能go较为流行的gin框架,go-zero的实现的web和gin还是有很大的区别的。

config.go文件

用来记载etc文件的yml的配置,具体配置项如下:

go-zero的路由机制解析_第5张图片
svc目录

该目录的文件将config的配置加载到控制器中。

handler目录

控制器负责转发路由,在routes.go中就是路由:

func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
	server.AddRoutes(
		[]rest.Route{
			{
				Method:  http.MethodGet,
				Path:    "/from/:name",
				Handler: WebHandler(serverCtx),
			},
		},
	)
}

zero的路由不用与gin,其是通过路由注册的方式。在zero中rest是zero的web对象,rest.RestConf是配置类。

go-zero的路由机制解析_第6张图片

rest.Server是web容器,包含引擎和路由,提供了众多方法配置路由和引擎。

go-zero的路由机制解析_第7张图片

rest.Route是一个整体的路由对象,包含请求方法,请求路径和处理逻辑。

go-zero的路由机制解析_第8张图片

AddRoutes是rest.Server提供的注册路由的方法,其参数是路由对象数组[]rest.Route

go-zero的路由机制解析_第9张图片
如上的注册逻辑,路由地址和方法以及处理逻辑均被注册到web容器中。

//路由对象也可分离出来

var routeList []rest.Route = []rest.Route{
  	//rest.Route
	//...
}

路由的处理函数还有一个参数,来自svc目录,该结构体封装了rest.RestConf也就是web容器的配置类。

go-zero的路由机制解析_第10张图片
转到路由处理函数,该配置类直到调用逻辑部分才被调用,如下图:
go-zero的路由机制解析_第11张图片
svc.ServiceContext就是封装了一下config结构体,logx.Logger是日志,context.Context是上下文连接,这个才是最重要的,就像gin的gin.Context一样。
go-zero的路由机制解析_第12张图片
这些并不需要开发者完全使用,结构体的多层封装是为了方便扩展,如果需求不高,直接使用默认的即可。

因此,这个封装的svc.ServiceContext的配置参数并不是必须的。存在这个参数可以改变对上下文,日志更改,不存在就是使用框架默认的。

那么一个处理函数必须包含那些必要的条件呢?接下来从一个函数来解析。

go-zero的路由机制解析_第13张图片
看到goctl生成的标准路由处理函数,之前已经说明了不需要svc.ServiceContext参数,那么http.HandlerFunc返回值函数就是必须的了。

go-zero的路由机制解析_第14张图片
看到http.HandlerFunc的源码其本身是一个函数类型,且携带了两个参数,一个响应一个请求。

那么就可以得到结论,路由处理函数是返回类型为http.HandlerFunc的任意函数。

只要自定义的函数满足上述条件,就可以当做路由处理函数注册到路由的rest.Route对象。

// 自定义处理函数
func MyHandler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		httpx.OkJsonCtx(r.Context(), w, "hello")
	}
}
//路由注册
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
	server.AddRoutes(
		[]rest.Route{
			{
				Method:  http.MethodGet,
				Path:    "/from/:name",
				Handler: WebHandler(serverCtx),
			},
			{
				Method: http.MethodGet,
				Path: "/hello",
				Handler: MyHandler(),
			},
		},
	)
}

启动web服务器,在浏览器端访问
在这里插入图片描述
go-zero的路由机制解析_第15张图片

另外,如下图所示查看处理函数的参数,响应参数和请求参数。

go-zero的路由机制解析_第16张图片
显然对于http的请求与响应操作。但是官方使用了httpx这个库,转到该库可以看到内部函数大多都包含http.ResponseWriter对其进一步封装。

go-zero的路由机制解析_第17张图片
开发者可以使用http.ResponseWriter元素返回参数,也可以使用httpx提供的方法返回数据。后者的优势是可以直接返回结构体不用在序列化操作。

// 返回短文
func ArticleController() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		//定义结构体
		type Article struct {
			Str string
		}
		art := Article{
			"开发者可以使用http.ResponseWriter元素返回参数,也可以使用httpx提供的方法返回数据。后者的优势是可以直接返回结构体不用在序列化操作。",
		}
		httpx.OkJson(w, art)
	}
}

路由处理函数可以模块化并自己封装,实现定制的服务。

最后就是api文件了,api文件是goctl插件一键化生成一个控制的配置文件,通过api的一些简单的配置可以直接生成一个控制,开发者只需要编写逻辑部分,非常方便。

go-zero的路由机制解析_第18张图片
有兴趣的可以了解api语法,使用自动生成工具会快捷很多。

你可能感兴趣的:(#,go-zero,golang,后端,微服务,服务器)