hz toolkit usage

hz is a tool provided by the Hertz framework for generating code. Currently, hz can generate scaffolding for Hertz projects based on thrift and protobuf’s IDL.

Install

  1. Make sure the GOPATH environment variable has been defined correctly (eg export GOPATH=~/go) and add $GOPATH/bin to the PATH environment (eg export PATH=$GOPATH/bin:$PATH); do not set GOPATH to a directory that the current user does not have read/write access to.
  2. Install hz:
go install github.com/cloudwego/hertz/cmd/hz@latest
  1. Verify that the installation was successful hz -v, if the following version message is displayed, the installation was successful
hz version v0.1.0

Note,Since hz creates soft links to its own binary, make sure that the installation path of hz has writable permissions.

Operating mode

To generate code using thrift or protobuf IDL, The corresponding compiler needs to be installed: thriftgo or protoc.

The code generated by hz, part of it is generated by the underlying compiler (usually about the struct defined in IDL), and the other part is the user-defined routing, method and other information in IDL. The user can run the code directly.

In terms of execution flow, when hz uses thrift IDL to generate code, hz calls thriftgo to generate the go struct code and executes itself as a plugin to thriftgo (named thrift-gen-hertz) to generate the rest of the code. This is also true when used with the protobuf IDL.

$> hz  ... --idl=IDL
    |
    | thrift-IDL
    |---------> thriftgo --gen go:... -plugin=hertz:... IDL
    |
    | protobuf-IDL
     ---------> protoc --hertz_out=... --hertz_opt=... IDL

How to install thriftgo/protoc:

thriftgo:

$ GO111MODULE=on go install github.com/cloudwego/thriftgo@latest

protoc:

// brew installation
$ brew install protobuf

// Official image installation, using macos as an example
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.19.4/protoc-3.19.4-osx-x86_64.zip
$ unzip protoc-3.19.4-osx-x86_64.zip
$ cp bin/protoc /usr/local/bin/protoc
// Make sure include/google goes under /usr/local/include
$ cp -r include/google /usr/local/include/google

Usage

Basic Usage

new: Create a new Hertz project

  1. Create a new project
// Execute under GOPATH, go mod name defaults to the current path relative to GOPATH, or you can specify your own
hz new

// Execute under non-GOPATH, you need to specify the go mod name
hz new -mod hertz/demo

// Tidy & get dependencies
go mod tidy

After executed, it generates a scaffold for the Hertz project in the current directory.

  1. Compiling Projects
go build
  1. Run the project and test it

Run the project:

./{{your binary}}

Test:

curl 127.0.0.1:8888/ping

If it returns {"message":"pong"}, it works.

Create a project based on thrift IDL

new: Create a new project

  1. Create the thrift IDL file in the current directory
// idl/hello.thrift
namespace go hello.example

struct HelloReq {
    1: string Name (api.query="name"); // Add api annotations for easier parameter binding
}

struct HelloResp {
    1: string RespBody;
}


service HelloService {
    HelloResp HelloMethod(1: HelloReq request) (api.get="/hello");
}
  1. Create a new project
// Execute under GOPATH
hz new -idl idl/hello.thrift

// Tidy & get dependencies
go mod tidy
  1. Modify the handler and add your own logic
// handler path: biz/handler/hello/example/hello_service.go
// where "hello/example" is the namespace of thrift IDL
// "hello_service.go" is the name of the service in the thrift IDL, all methods defined by the service will be generated in this file

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

        resp := new(example.HelloResp)

        // You can modify the logic of the entire function, not just the current template
        resp.RespBody = "hello," + req.Name // added logic

        c.JSON(200, resp)
}
  1. Compile the project
go build
  1. Run the project and test it

Run the project:

./{{your binary}}

Test:

curl --location --request GET 'http://127.0.0.1:8888/hello?name=hertz'

If it returns {"RespBody":"hello,hertz"}, it works.

update: Update an existing project

  1. If your thrift IDL is updated, for example:
// idl/hello.thrift
namespace go hello.example

struct HelloReq {
    1: string Name (api.query="name");
}

struct HelloResp {
    1: string RespBody;
}

struct OtherReq {
    1: string Other (api.body="other");
}

struct OtherResp {
    1: string Resp;
}


service HelloService {
    HelloResp HelloMethod(1: HelloReq request) (api.get="/hello");
    OtherResp OtherMethod(1: OtherReq request) (api.post="/other");
}

service NewService {
    HelloResp NewMethod(1: HelloReq request) (api.get="/new");
}
  1. Switch to the directory where the new command was executed and update the modified thrift IDL
hz update -idl idl/hello.thrift
  1. As you can see

    Add new method under “biz/handler/hello/example/hello_service.go”
    The file “new_service.go” and the corresponding “NewMethod” method have been added under “biz/handler/hello/example”

Now let’s develop the “OtherMethod” interface

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

   resp := new(example.HelloResp)

   // You can modify the logic of the entire function, not just the current template
   resp.RespBody = "hello," + req.Name // added logic

   c.JSON(200, resp)
}

// OtherMethod .
// @router /other [POST]
func OtherMethod(ctx context.Context, c *app.RequestContext) {
   var err error
   // The model file corresponding to example.OtherReq will also be regenerated
   var req example.OtherReq
   err = c.BindAndValidate(&req)
   if err != nil {
      c.String(400, err.Error())
      return
   }

   resp := new(example.OtherResp)

   // added logic
   resp.Resp = "Other method: " + req.Other

   c.JSON(200, resp)
}
  1. Compile the project
go build
  1. Run the project and test it

Run the project:

./{{your binary}}

Test:

curl --location --request POST 'http://127.0.0.1:8888/other' \
--header 'Content-Type: application/json' \
--data-raw '{
    "Other": "other method"
}'

If it returns {"Resp":"Other method: other method"}, it works.

Create a project based on protobuf IDL

new: Create a new project

  1. Create the protobuf IDL file in the current directory

    Note: In order to support api annotations in protobuf, please import the following file in the proto file where the annotation is used

// idl/api.proto; Annotation extension
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;
}

Main IDL definition

// 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";
  }
}
  1. Create a new project
// Execute under GOPATH, if the dependencies of the main IDL and the main IDL are not in the same path, you need to add the -I option, its meaning is IDL search path, equivalent to the option "-I" for protoc
hz new -I idl -idl idl/hello/hello.proto

// Tidy & get dependencies
go mod tidy
  1. Modify the handler and add your own logic
// handler path: biz/handler/hello/hello_service.go
// where "/hello" is the last level of go_package in protobuf IDL
// "hello_service.go" is the name of the service in protobuf IDL, all methods defined by the service will be generated in this file

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

   // You can modify the logic of the entire function, not just the current template
   resp.RespBody = "hello," + req.Name // added logic

   c.JSON(200, resp)
}
  1. Compile the project
go build
  1. Run the project and test it

Run the project:

./{{your binary}}

Test:

curl --location --request GET 'http://127.0.0.1:8888/hello?name=hertz'

If it returns {"RespBody":"hello,hertz"}, it works.

update: Update an existing Hertz project

  1. If your protobuf IDL is updated, for example:
// 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;
}

message OtherReq {
  string Other = 1[(api.body)="other"];
}

message OtherResp {
  string Resp = 1;
}

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

service NewService {
  rpc Method3(OtherReq) returns(OtherResp) {
    option (api.get) = "/new";
  }
}
  1. Switch to the directory where the new command was executed and update the modified IDL
hz update -I idl -idl idl/hello/hello.proto
  1. As you can see

    Add new method under “biz/handler/hello/hello_service.go”
    The file “new_service.go” and the corresponding “Method3” method have been added under “biz/handler/hello”

Now let’s develop the “Method2” interface

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

   // You can modify the logic of the entire function, not just the current template
   resp.RespBody = "hello," + req.Name // added logic

   c.JSON(200, resp)
}

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

   resp := new(hello.OtherResp)

   // added logic
   resp.Resp = "Other method: " + req.Other

   c.JSON(200, resp)
}
  1. Compile the project
go build
  1. Run the project and test it

Run the project:

./{{your binary}}

Test:

curl --location --request POST 'http://127.0.0.1:8888/other' \
--header 'Content-Type: application/json' \
--data-raw '{
    "Other": "other method"
}'

If it returns {"Resp":"Other method: other method"}, it works.

The structure of the generated code

The structure of the code generated by hz is similar. The following is an example of the structure of the code generated by the section “Create a project based on thrift IDL” to illustrate the meaning of the code generated by hz.

.
├── biz                                // business layer, which stores business logic related processes
│   ├── handler                        // store handler file
│   │   ├── hello                      // hello/example corresponds to the namespace defined in thrift IDL; for protobuf IDL, it corresponds to the last level of go_package
│   │   │   └── example
│   │   │       ├── hello_service.go   // the handler file, the user will implement the method defined by the IDL service in this file, it will search for the existing handler in the current file when "update" command, and append a new handler to the end
│   │   │       └── new_service.go     // same as above, each service defined in IDL corresponds to a file
│   │   └── ping.go                    // ping handler carried by default, used to generate code for quick debugging, no other special meaning
│   ├── model                          // IDL content-related generation code
│   │   └── hello                      // hello/example corresponds to the namespace defined in thrift IDL; for protobuf IDL, it corresponds to the last level of go_package
│   │     └── example
│   │         └── hello.go             // the product of thriftgo, It contains go code generated from the contents of hello.thrift definition. And it will be regenerated when use "update" command.
│   └── router                         // generated code related to the definition of routes in IDL
│       ├── hello                      // hello/example corresponds to the namespace defined in thrift IDL; for protobuf IDL, it corresponds to the last level of go_package
│       │   └── example
│       │       ├── hello.go           // the route registration code generated for the routes defined in hello.thrift by hz; this file will be regenerated each time the relevant IDL is updated
│       │       └── middleware.go      // default middleware function, hz adds a middleware for each generated route group by default; when updating, it will look for the existing middleware in the current file and append new middleware at the end
│       └── register.go                // call and register the routing definition in each IDL file; when a new IDL is added, the call of its routing registration will be automatically inserted during the update; do not edit
├── go.mod                             // go.mod file, if not specified on the command line, defaults to a relative path to GOPATH as the module name
├── idl                                // user defined IDL, location can be arbitrary
│   └── hello.thrift
├── main.go                            // program entry
├── router.go                          // user defined routing methods other than IDL
└── router_gen.go                      // the route registration code generated by hz, for calling user-defined routes and routes generated by hz

Supported api annotations

Field annotation can be used forparameter binding and validation

Method annotation can be used to generate code that related to route registration

Supported api annotations

Field annotation
annotationdescription
api.raw_bodygenerate “raw_body” tag
api.querygenerate “query” tag
api.headergenerate “header” tag
api.cookiegenerate “cookie” tag
api.bodygenerate “json” tag
api.pathgenerate “path” tag
api.formgenerate “form” tag
api.go_tag (protobuf)
go.tag (thrift)
passing go_tag through will generate the content defined in go_tag
api.vdgenerate “vd” tag
Method annotation
annotationdescription
api.getdefine GET methods and routes
api.postdefine POST methods and routes
api.putdefine PUT methods and routes
api.deletedefine DELETE methods and routes
api.patchdefine PATCH methods and routes
api.optionsdefine OPTIONS methods and routes
api.headdefine HEAD methods and routes
api.anydefine ANY methods and routes

Usage:

Field annotation:

Thrift:

struct Demo {
    1: string Demo (api.query="demo", api.path="demo");
    2: string GoTag (go.tag="goTag:"tag"");
    3: string Vd (api.vd="$!='your string'");
}

Protobuf:

message Demo {
  string Demo = 1[(api.query)="demo",(api.path)="demo"];
  string GoTag = 2[(api.go_tag)="goTag:"tag""];
  string Vd = 3[(api.vd)="$!='your string'"];
}
Method annotation:

Thrift:

service Demo {
    Resp Method(1: Req request) (api.get="/route");
}

Protobuf:

service Demo {
  rpc Method(Req) returns(Resp) {
    option (api.get) = "/route";
  }
}

Command line parameter description

Global:

$ hz --help
NAME:
   hz - A idl parser and code generator for Hertz projects

USAGE:
   hz [global options] command [command options] [arguments...]

VERSION:
   0.0.1

COMMANDS:
   new      Generate a new Hertz project
   update   Update an existing Hertz project
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --help, -h     show help (default: false)
   --verbose      turn on verbose mode (default: false)
   --version, -v  print the version (default: false)
  • new: Create a new Hertz project
  • update: Updating an existing Hertz project

New:

$ hz help new
NAME:
   hz new - Generate a new Hertz project

USAGE:
   hz new [command options] [arguments...]

OPTIONS:
   --client_dir value                Specify the client path. If not specified, no client code is generated.
   --customize_layout value          Specify the layout template. ({{Template Profile}}:{{Rendering Data}})
   --customize_package value         Specify the package template. ({{Template Profile}}:)
   --exclude_file value, -E value    Specify the files that do not need to be updated.  (accepts multiple inputs)
   --handler_dir value               Specify the handler path.
   --idl value                       Specify the IDL file path. (.thrift or .proto)  (accepts multiple inputs)
   --json_enumstr                    Use string instead of num for json enums when idl is thrift. (default: false)
   --model_dir value                 Specify the model path.
   --module value, --mod value       Specify the Go module name to generate go.mod.
   --no_recurse                      Generate master model only. (default: false)
   --option_package value, -P value  Specify the package path. ({include_path}={import_path})  (accepts multiple inputs)
   --out_dir value                   Specify the project path.
   --proto_path value, -I value      Add an IDL search path for includes. (Valid only if idl is protobuf)  (accepts multiple inputs)
   --protoc value, -p value          Specify arguments for the protoc. ({flag}={value})                    (accepts multiple inputs)
   --service value                   Specify the service name.
   --snake_tag                       Use snake_case style naming for tags. (Only works for 'form', 'query', 'json') (default: false)
   --thriftgo value, -t value        Specify arguments for the thriftgo. ({flag}={value})  (accepts mul
  • client_dir: Specify the path to generate client-side code, if not specified, it will not be generated; currently generates a global client for each service, and will provide rich client code capabilities later
  • customize_package: Customize the project package related templates, mainly for the handler template. For details, see: hz custom template use
  • exclude_file: Files that do not need to be updated(relative to the project path, multiple supported)
  • handler_dir: Specify the handler generation path, the default is “biz/handler”
  • idl: IDL file path (.thrift or .proto)
  • json_enumstr: When IDL is thrift, json enums uses string instead of num (option passed through to thriftgo)
  • model_dir: Specify the model generation path, the default is “biz/model”
  • module/mod: Specify the name of go mod, which must be specified under non-GOPATH, and default to a path relative to GOPATH under GOPATH.
  • no_recurse: Generate only the model code for main IDL
  • option_package/P: Specify the path to the package, ({include_path}={import_path})
  • out_dir: Specify the project build path
  • proto_path/I: When IDL is protobuf, specify the search path for IDL, equivalent to the option “-I” for protoc
  • protoc/p: Option passed through to protoc ({flag}={value})
  • service: Service name, reserved for later service discovery and other functions
  • snake_tag: The tag is named in snake_case style(only works for form、query、json )
  • thriftgo/t: Option passwd through to thrift ({flag}={value})
  • unset_omitempty: When IDL is protobuf, the model field is generated and the omitempty tag is removed; when IDL is thrift, whether to add omitempty is determined by whether the field is “optional” or “required”

Update:

$ hz help update
NAME:
   hz update - Update an existing Hertz project

USAGE:
   hz update [command options] [arguments...]

OPTIONS:
   --client_dir value                Specify the client path. If not specified, no client code is generated.
   --customize_package value         Specify the package template. ({{Template Profile}}:)
   --exclude_file value, -E value    Specify the files that do not need to be updated.  (accepts multiple inputs)
   --handler_dir value               Specify the handler path.
   --idl value                       Specify the IDL file path. (.thrift or .proto)  (accepts multiple inputs)
   --json_enumstr                    Use string instead of num for json enums when idl is thrift. (default: false)
   --model_dir value                 Specify the model path.
   --no_recurse                      Generate master model only. (default: false)
   --option_package value, -P value  Specify the package path. ({include_path}={import_path})  (accepts multiple inputs)
   --out_dir value                   Specify the project path.
   --proto_path value, -I value      Add an IDL search path for includes. (Valid only if idl is protobuf)  (accepts multiple inputs)
   --protoc value, -p value          Specify arguments for the protoc. ({flag}={value})                    (accepts multiple inputs)
   --snake_tag                       Use snake_case style naming for tags. (Only works for 'form', 'query', 'json') (default: false)
   --thriftgo value, -t value        Specify arguments for the thriftgo. ({flag}={value})  (accepts multiple inputs)
   --unset_omitempty                 Remove 'omitempty' tag for generated struct. (default: false)
  • client_dir: Specify the path to generate client-side code, if not specified, it will not be generated; currently generates a global client for each service, and will provide rich client code capabilities later. Note: If you update the same set of IDL, the value of client_dir needs to be the same as when using new, otherwise it will generate redundant code that needs to be removed by the user.
  • customize_package: Customize the project package related templates, mainly for the handler template. For details, see:hz custom template use. Note: For an existing handler file, a handler function will be added according to the default template, and for handler files that do not exist yet, a handler will be generated according to a custom template.
  • exclude_file: Files that do not need to be updated(relative to the project path, multiple supported)
  • handler_dir: Specify the handler generation path, the default is “biz/handler”; Note: If you update the same set of IDL, the value of handler_dir needs to be the same as when using new, otherwise it will generate redundant code that needs to be removed by the user.
  • idl: IDL file path (.thrift or .proto)
  • json_enumstr: When IDL is thrift, json enums uses string instead of num (option passed through to thriftgo)
  • model_dir: Specify the model generation path, the default is “biz/model”; Note: If you update the same set of IDL, the value of model_dir needs to be the same as when using new, otherwise it will generate redundant code that needs to be removed by the user.
  • no_recurse: Generate only the model code for main IDL
  • option_package/P: Specify the path to the package, ({include_path}={import_path})
  • out_dir: Specify the project build path
  • proto_path/I: When IDL is protobuf, specify the search path for IDL, same as protoc’s -I command
  • protoc/p: Option passed through to protoc ({flag}={value})
  • snake_tag: The tag is named in snake_case style(only works for form、query、json )
  • thriftgo/t: Option passwd through to thrift ({flag}={value})
  • unset_omitempty: When IDL is protobuf, the model field is generated and the omitempty tag is removed; when IDL is thrift, whether to add omitempty is determined by whether the field is “optional” or “required”

Notes

Notes on using protobuf IDL

hz currently supports the syntax of proto2 / proto3

We hope that users specify go_package when defining the protobuf IDL, so that one is consistent with the semantics of protobuf and the location of the generated model can be determined by go_package. If the user does not specify go_package, hz will default the package of the proto file to go_package, which may have some unintended naming conflicts.

For example, go_package can be defined like this

option go_package = "hello.world"; // or hello/world

The generated path of model will be:

${project path}/${model_dir}/hello/world

The handler file will take the last level of go_package as the generation path, and its generation path will be:

${project path}/${handler_dir}/world

The router registration file will also take the last level of the go_package as the generation path, and the generation path will be:

${project path}/biz/router/world

Notes on using thrift IDL

hz has no special requirements for the definition of thrift IDL, it only needs to comply with the grammar specification. The code generation path will be related to the thrift namespace

For example, a namespace can be defined like this

 namespace go hello.world

The generated path of model will be:

${project path}/${model_dir}/hello/world

The handler file will take namespace as the generation path, and its generation path will be:

${project path}/${handler_dir}/hello/world

The router registration file will also take namespace as the generation path, and its generation path will be:

${project path}/biz/router/hello/world

Description of the behavior when using the update command

  1. Notes on using custom path

For the convenience of user, hz provides custom handler paths, model paths, templates, etc. However, hz does not save the current project information when creating a new project, so it can be considered as a stateless update when using the update command. Therefore, for the same set of IDL in new and update, using different custom information may result in duplicate code, for example, as follows:

Create a new project:

hz new -idl demo.thrift

// In this case, hz will generate the model under "biz/model"

Update an existing project:

hz update -idl demo.thrift --model_dir=my_model

// In this case, hz will not update the model code under "biz/model", but under "my_model"; then the code under "biz/model" and "my_model" will be duplicated, and the new handler will depend on "my_model",while the previous handler will depend on "biz/model". In this case, you need to delete & change some code manually.

Therefore, we hope that user use the update command with custom paths “client_dir”, “model_dir”, “handler_dir”, preferably same as new.

  1. Behavior of update handler

hz will generate handlers based on default/custom template when creating a new project, where each service generates a file that contains all the handler code defined by the service; if IDL defines multiple services, each service will generate a file, and these files are in the same path; for example:

// demo.thrift
namespace go hello.example

service Service1 {
    HelloResp Method1(1: HelloReq request) (api.get="/hello");
}

service Service2 {
    HelloResp Method2(1: HelloReq request) (api.get="/new");
}

// Then the handler file generated by the IDL is as follows:
${handler_dir}/${namespace}/service1.go -> method1
${handler_dir}/${namespace}/service2.go -> method2

When a new method is added to the IDL, the handler template will be added at the end of the corresponding service file; note that the handler added here will use the default template, and the new service file will use a custom template if appropriate.

  1. Behavior of update router

The router code generated by hz in new mainly includes the following three:

  • biz/router/${namespace}/${idlName}.go: Each primary IDL generates a corresponding routing registration code file, which registers all the routes defined in the IDL in a routing group, and sets the default middleware.
  • biz/router/${namespace}/middleware.go: The default middleware function corresponding to each primary IDL, which can be modified by the user to add specific middleware logic to a particular route.
  • biz/router/register.go: This file is responsible for calling the route registration generated by different IDL; for example, if i define service in both IDL “demo1.thrift” and “demo2.thrift”, then both files will generate the corresponding route registration code. register.go is responsible for calling the route registration functions of these two parts.

Based on the above description, a description of the router’s behavior during update is given:

  • biz/${namespace}/${idlName}.go: Regenerate based on IDL every time, users should not change the code of this file, otherwise the code will be lost.
  • biz/${namespace}/middleware.go: Appends a currently unavailable middleware to the end each time.
  • biz/router/register.go: If there is a new IDL, the route registration method of the new IDL will be inserted.