Cloudwego之herz框架初体验一 | 青训营

232 阅读5分钟

说起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

image.png

1.2使用脚手架创建一个项目

#创建一个文件夹
mkdir hz_demo
cd hz_demo
#使用命令创建程序
hz new -mod demo
#如果执行没有出错,创建成功

现在你可以使用goland 或者vscode打开这个项目。

运行项目

#下载依赖,该命令只在第一次项目第一次运行时执行一次。
go mod tidy
#运行
go run .

如果你在命令行中看到监听端口,那么程序运行成功。

image.png 你可以在goland中添加配置直接运行,选择添加go build配置。

image.png

选择好后,直接应用,最后运行。

1.3生成目录分析

image.png 如上图所述,我们主要在biz/handler中来写我们的controller代码,在router.go中注册我们的路由。至于idl自动生成的代码我们后面再介绍。

1.4注册我们自己的路由

1.首先在router.go中注册一条路由,如下图所示:

image.png 路由的地址是/demoTest,处理函数是handler包下DemoTest函数。

image.png

//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")
}

测试

image.png

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":  "请求成功",
    })
}

image.png 可以看出我们返回的值是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,
        },
    })
}

image.png

我们看出我们可以表示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",
    })
}

image.png

可以看出只有首字母大写的字段才能被返回,这是因为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的值。