说起web,我们往往想到的是java的spring框架。go作为一门快速入门的语言,提供了自己的标准库来完成各种网络需求。框架的存在只是方便我们开发,开源框架有许多,最为出名易用的莫过于gin了,cloudwego仿照了gin提供的接口提供了http服务器hertz。但是地层代码中hertz框架提供了不同的网络库。通过hertz框架,我们可以将我们的服务以http接口的方式提供给用户。
1.1安装脚手架hz
go install github.com/cloudwego/hertz/cmd/hz@latest
安装后可以使用hz --version命令查看是否安装成功。如果你使用hz命令未成功,请查看你的GOPATH是否在系统环境变量中。可以使用go env查看自己的GOPATH环境变量。
go env GOPATH
1.2使用脚手架创建一个项目
#创建一个文件夹
mkdir hz_demo
cd hz_demo
#使用命令创建程序
hz new -mod demo
#如果执行没有出错,创建成功
现在你可以使用goland 或者vscode打开这个项目。
运行项目
#下载依赖,该命令只在第一次项目第一次运行时执行一次。
go mod tidy
#运行
go run .
如果你在命令行中看到监听端口,那么程序运行成功。
你可以在goland中添加配置直接运行,选择添加go build配置。
选择好后,直接应用,最后运行。
1.3生成目录分析
如上图所述,我们主要在biz/handler中来写我们的controller代码,在router.go中注册我们的路由。至于idl自动生成的代码我们后面再介绍。
1.4注册我们自己的路由
1.首先在router.go中注册一条路由,如下图所示:
路由的地址是/demoTest,处理函数是handler包下DemoTest函数。
//router.go/customizedRegister func
r.GET("/demoTest", handler.DemoTest)
//biz/handler
func DemoTest(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "demo test")
}
测试
1.4使用http的常用方法
官方文档请查看详情信息可以查看www.cloudwego.io/zh/docs/her…
现在我们可以处理http的get请求了,如果发送的是其他方法请求呢?
我们只需要在router.go中注册时,使用对应的方法就可以了。其中在http请求中我们最常用的请求是GET,POST,PUT,DELETE四个方法。他们在hz框架中注册方法的参数都是一致的。第一个参数都是请求路径,后面的所有参数都是处理方法。例如我们可以将这四个常用的请求方法的handler(java中的controller)都注册成DemoTest方法。
r.GET("/demoTest", handler.DemoTest)
r.POST("/demoTest", handler.DemoTest)
r.PUT("/demoTest", handler.DemoTest)
r.DELETE("/demoTest", handler.DemoTest)
至此,我们现在学会了处理http请求的不同方法。下一步我们要学习的时如何处理http的返回值。
1.5返回值处理
func DemoTest(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "demo test")
}
上面demoTest代码中我们可以看到,我们返回了一个字符串"demo test"。
既然我们可以通过c.String方法返回一个字符串。那么我们是否有c.JSON方法吗?
显然是有这么一个方法的。现在我们将demoTest修改一下。
func DemoTest(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, utils.H{
"code": 200,
"msg": "请求成功",
})
}
可以看出我们返回的值是json格式。你有没有想过c.String和c.JSON的第一个参数是什么?
显然第一个参数是http的状态码,hz框架提供了一些常量来表示这些状态码他们都在consts包下,通常用consts.StatusXXX开始。如果你不了解状态码,可以查看一下下面这篇文章。
developer.mozilla.org/zh-CN/docs/…
通常我们用200表示请求成功,30x表示重定向,40x表示请求错误,50x表示服务器内部异常。
c.String中第二个参数容易理解就是我们要返回的字符串。c.JSON中返回一个utils.H对象又是什么东西。实际上我们可以安装ctrl+鼠标左键可以看到他的定义。
// H is a shortcut for map[string]interface{}
type H map[string]interface{}
utils.H是一个key为string,value为空接口类型的map集合。我们可以推测H表示hashmap的意思。这样我们可以使用map来表示json的key和val。因为val是个空接口(可以理解为java中Object或者范型,实际上并不是一种东西),同样我们可以使用utils.H来表示嵌套类型。
func DemoTest(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, utils.H{
"name": "zhangsan",
"age": 18,
"score": []int{1, 2, 3, 4, 5},
"relations": utils.H{
"father": "zhangsanfeng",
"mother": "none",
"wife": nil,
},
})
}
我们看出我们可以表示json中的不同类型,有数组类型,字符串类型,数字型,以及我们要的嵌套类型和空指针类型null。
我们也可以通过结构体返回JSON格式数据。
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Password string
testField1 string
testField2 string `json:"tf2"`
}
func Demo2(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, User{
Name: "zhangsan",
Age: 123,
Password: "123456",
testField1: "testField1",
})
}
可以看出只有首字母大写的字段才能被返回,这是因为golang以字段首字母大小写来表示对应字段是否对外暴露。对应java中class public和private权限控制。当我们不对结构体打上标签,默认是以字段名称来表示json中key属性,例如Password并为打上json标签,对应的key为大写的Password。如果有json标签,则为标签为key。
也就是说,结构体首字母大写允许向外界暴露使用,但是在json中使用key为对应的字段名称。我们可以通过tag中json标签来修改转换为json格式的key。
总结一下:
我们使用处理函数中的第二个参数RequestContext来返回数据。通常有String,JSON格式,这些函数都是两个参数的函数,第一个参数的请求返回的状态码,第二个参数是要返回的数据。JSON格式用map集合表示。当然我们也可以使用结构体表示JSON格式,只需要在结构体上打上对应Tag,如果没有标签,默认以字段名为key的值。