Gorm、KiteX、Hertz框架(3) | 青训营笔记

310 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天

这次我们来看看Hertz框架。

具体的api文档在cloudwego[基本特性 | CloudWeGo]

库的安装参照文档即可。

创建服务端

导入hertz后,我们可以使用default设置开启一个默认的服务。

h := server.Default()

此时就可以启动一个server了。但是这个server还没有配置路由,所以你访问不了他。

你可以使用WithHostPorts来绑定我们需要的ip与端口:

h := server.Default(server.WithHostPorts(":8080"))

这样我们就绑到了0.0.0.0:8080上了。

创建完成后,我们就可以添加我们的路由,随后使用Spin()方法开始监听端口了。

server默认使用的是字节自家的netpoll。你也可以使用new来创建服务端的时候指定是否使用netpoll还是go原生的网络库。

server.New(server.WithTransport(standard.NewTransporter))
server.New(server.WithTransport(netpoll.NewTransporter))

standard就是go原生,而netpoll就是默认的网络库。目前netpoll还没有支持TLS所以如果要使用TLS的话还得用原生。文档中提到了两者的不同之处。通俗来讲就是小规模的读写操作使用netpoll性能会更好,而对于大规模的读写操作,使用go原生会好些,netpoll会存在内存读写压力。

路由

路由注册

Hertz提供了GET、POST、DELETE、PUT、PATCH、HEAD、OPTIONS和ANY的路由注册,可以直接使用hertz提供的相关的方法,或者使用Handle来手动的指定。Hertz也提供了静态文件注册。

这里不考虑中间件。

	r.GET("/ping", handler.Ping)

	r.POST("/post", func(c context.Context, ctx *app.RequestContext) {
		ctx.String(consts.StatusOK, "post")
	})

其他的方法类似。

而Handle方法,可以让我们注册自定义路由,例如我们可以自定一个REPLACE方法,然后使用Handle去注册他:

	r.Handle("REPLACE", "/replace", func(c context.Context, ctx *app.RequestContext) {
		ctx.String(consts.StatusOK, "replace")
	})

路由类型

hertz的路由分为三种,分别是静态路由、参数路由和通配路由。这三者的路由优先级也是从高到低的。如果能够匹配上高级的将会转发到相应的业务逻辑中。

静态路由就是我们的路径为静态的。上文中我们使用的"/ping"、"/post"就属于静态路由。

如果我们在url中间使用了:name类型的字符串那么其将会成为占位符,会更具具体的请求而变化:

	r.GET("/get/:name", func(c context.Context, ctx *app.RequestContext) {
		ctx.String(consts.StatusOK, fmt.Sprintf("hello, %s", ctx.Param("name")))
	})

那么我们访问"localhost:port/get/lihua",就会返回“hello, lihua"。

我们可以在requestcontext中使用Parma来获取参数,Query方法用于获取url中的参数(?后面的等号键值对类型的参数,如:/get?name=lihua, 就可以使用Query("name")来取得lihua这个字符串)

注意,我们我们访问的url是"/get/",或者"/get/lihua/photo"这样的是不会匹配的。

最后是我们的通配路由:和参数路由类似:

	r.GET("/get/:name/*item", func(c context.Context, ctx *app.RequestContext) {
		ctx.JSON(consts.StatusOK, utils.H{
			"Name": ctx.Param("name"),
			"item": ctx.Param("item"),
		})
	})

此时"/get/lihua/photo", "/get/lihua/phone/photo", "/get/lihua/"都会路由到这个业务逻辑中。

参数绑定

Hertz提供给了一个方便将请求参数序列化到结构体中的方法,需要配合tag使用。

func Test_bind(c context.Context, ctx *app.RequestContext) {

	type Data struct {
		Name    string `path:"name" json:"name"`
		Age     string `query:"age" json:"age"`
		Message string `json:"message"`
	}

	var p Data

	err := ctx.BindAndValidate(&p)
	if err != nil {
		fmt.Printf("Bad input, %s", err)
                return
	}

	ctx.JSON(consts.StatusOK, fmt.Sprintf("%#v", p))

}

//curl --location --request GET "http://localhost:8888/get/lihua?age=12" \
//--header "Content-Type: application/json" --data-raw '{"message": "this is test"}'

// "handler.Data{Name:\"lihua\", Age:\"12\", Message:\"this is test\"}"

path tag说明这个参数要从路径参数中来,值为路径参数的名称。你可将其理解为上文的Param和Query。 如果我们的body是json,那么我们可以将其序列化到结构体。很方便的一个功能。

具体的tag可以在文档中看到[绑定与校验 | CloudWeGo]

这里我们使用的是bindandvalidate,也可以单独使用bind和validate这两个方法。

hz脚手架

hertz提供了一个脚手架hz。可以帮助我们直接生成代码。hz的安装在文档中有所提及,跟着步骤走即可。

hz默认在GOPATH下的src目录释放代码。如果你想要在其他地方释放代码需要添加-module name参数。

hz new生成的默认代码如下结构:

.
├── biz
│   ├── handler
│   │   └── ping.go
│   └── router
│       └── register.go
├── go.mod
├── main.go
├── router.go
└── router_gen.go

main.go是我们的程序入口。在此我们创建server,并调用register注册我们的路由,随后使用spin进行监听。

我们的注册操作在router.go中。这里我们写入我们需要注册那些路由。相应的业务逻辑则是在./biz/handler中。./biz/router则是在我们使用IDL的时候会使用到。