Hertz 学习笔记(30)

306 阅读2分钟

继续学习 hz 的例子

使用 hz 与 protobuf 生成服务端代码的示例

在当前文件夹里新建 idl 文件夹,然后在这个文件夹里面先放一个 api.proto 用来扩展 protobuf 的功能,比如支持 API 注解。

syntax = "proto2";

package api;

import "google/protobuf/descriptor.proto";

option go_package = "/api";

extend google.protobuf.FieldOptions {
  optional string raw_body = 50101;
  optional string query = 50102;
  optional string header = 50103;
  optional string cookie = 50104;
  optional string body = 50105;
  optional string path = 50106;
  optional string vd = 50107;
  optional string form = 50108;
  optional string go_tag = 51001;
  optional string js_conv = 50109;
}

extend google.protobuf.MethodOptions {
  optional string get = 50201;
  optional string post = 50202;
  optional string put = 50203;
  optional string delete = 50204;
  optional string patch = 50205;
  optional string options = 50206;
  optional string head = 50207;
  optional string any = 50208;
  optional string gen_path = 50301;
  optional string api_version = 50302;
  optional string tag = 50303;
  optional string name = 50304;
  optional string api_level = 50305;
  optional string serializer = 50306;
  optional string param = 50307;
  optional string baseurl = 50308;
}

extend google.protobuf.EnumValueOptions {
  optional int32 http_code = 50401;
}

主要的 idl 文件放在单独的文件夹 hello 里,文件名也叫 hello.proto

// idl/hello/hello.proto
syntax = "proto3";

package hello;

option go_package = "hertz/hello";

import "api.proto";

message HelloReq {
  string Name = 1[(api.query)="name"];
}

message HelloResp {
  string RespBody = 1;
}

service HelloService {
  rpc Method1(HelloReq) returns(HelloResp) {
    option (api.get) = "/hello";
  }
}

然后回到 idl 文件夹的上一级,在这里创建新项目:

// 如果主 IDL 的依赖和主 IDL 不在同一路径下,需要加入 -I 选项,其含义为 IDL 搜索路径,等同于 protoc 的 -I 命令
hz new -I idl -idl idl/hello/hello.proto

// 整理 & 拉取依赖
go mod tidy

之后就是修改 handler 里面的逻辑了,对应的文件在 biz/handler/hello/hello_service.go,其中 /hello 是 protobuf idl 中 go_package 的最后一级,hello_service.go 是 protobuf idl 中 service 的名字,所有 service 定义的方法都会生成在这个文件中。

// Method1 .
// @router /hello [GET]
func Method1(ctx context.Context, c *app.RequestContext) {
   var err error
   var req hello.HelloReq
   err = c.BindAndValidate(&req)
   if err != nil {
      c.String(400, err.Error())
      return
   }

   resp := new(hello.HelloResp)

   // 你可以修改整个函数的逻辑,而不仅仅局限于当前模板
   resp.RespBody = "hello," + req.Name // 添加的逻辑

   c.JSON(200, resp)
}

下一步编译项目:

go build

然后找到文件夹里的可执行文件运行,然后再开一个终端运行 curl --location --request GET 'http://127.0.0.1:8888/hello?name=hertz',如果返回 {"RespBody":"hello,hertz"},说明接口调通。