Controller Generating - 图1tip

This feature is available from version v2.5. Currently, this command only supports HTTP interface development; for GRPC parts, please refer to the gen pb command. In the future, HTTP and GRPC may be unified to use this command to generate controller and SDK source code.

Introduction

Pain Points Solved

When developing a project, it often starts with designing the API interface based on business requirements and scenarios, using proto or golang struct to design the API input and output. Then, a corresponding controller implementation is created, and an SDK (under the condition of the Golang language) may also be provided for internal/external service calls. The following pain points may arise during development:

  • Repetitive code work is cumbersome. After creating input and output definition files in the API, corresponding files need to be created in the controller directory, along with controller initialization code. The operation of repeatedly copying input and output structure names from the API code is cumbersome.
  • No reliable normative constraints between the API and controller. Apart from certain naming constraints for the API, there are no constraints for controller creation and method naming. The high flexibility makes it difficult to enforce consistency between API structure names and controller method names, leading to potential maintenance costs as interfaces increase.
  • High probability of code file conflicts in team development collaboration. When multiple people execute changes to a file, the probability of file conflicts increases, leading to unnecessary energy expenditure in resolving these conflicts.
  • Lack of automated API HTTP SDK generation tool. After developing the API, immediately providing it for internal or external calls often requires manually maintaining the SDK code, which can be time-consuming and costly.

Command Features

  • Standardizes API definition and controller file naming, as well as controller implementation method naming.
  • Establishes the association between API definitions and controller code, facilitating quick location of API implementations.
  • Automatically generates controller interface, controller initialization files and code, and interface initialization code based on API definitions.
  • Automatically generates easy-to-use HTTP SDK code according to API definitions. This feature is configurable and turned off by default.
  • Supports File Watch automation mode: automatically incrementally updates corresponding controller and SDK code when an API structure definition file changes.

Pre-conditions

Important Norms 🔥

One of the purposes of this command is to standardize api code writing, which requires some important norms to be understood (otherwise the code cannot be generated):

  • api layer’s API definition file path needs to satisfy /api/module/version/definition_file.go, for example: /api/user/v1/user.go, /api/user/v1/user_delete.go, etc.
    • Module refers to the division of API modules, which can be split according to different business attributes for easier aggregation and maintenance. Modules can also be considered as specific business resources.
    • Version is usually defined as v1/v2, etc., for compatibility version control of API. Different versions are marked by different version numbers when compatibility updates occur. The first version is managed with v1 by default.
    • Definition file refers to the API input and output definition files, where each API is usually maintained independently in a separate go file. Of course, it also supports putting multiple APIs in one go file for unified maintenance.
  • Structure names in api definition should conform to the naming convention of Operation+Req and Operation+Res, e.g., GetOneReq/GetOneRes, GetListReq/GetListRes, DeleteReq/DeleteRes, etc.
    • The operation refers to the current API module’s operation name, typically corresponding to CRUD as: Create, Update, GetList/GetOne, Delete.

Below is a Hello interface example in the project template:

Controller Generating - 图2

Suggested Naming

We provide some suggested naming conventions for common API definitions for your reference:

Operation NameSuggested NamingNotes
Query ListGetListReq/ResUsually to fetch paginated query data records from the database
Query DetailsGetOneReq/ResUsually requires passing the primary key condition to query record details from the database
Create ResourceCreateReq/ResTypically used to insert one or more data records into a table
Modify ResourceUpdateReq/ResTypically used to modify one or more data records in a table according to certain conditions
Delete ResourceDeleteReq/ResTypically used to delete one or more data records in a table according to certain conditions

Command Usage

This command analyzes the code within the specified api API definition directory and automatically generates the corresponding controller/SDK Go code files.

Manual Mode

To manually execute the command line, run gf gen ctrl in the project’s root directory. It will completely scan the api API definition directory and generate corresponding code.

  1. $ gf gen ctrl -h
  2. USAGE
  3. gf gen ctrl [OPTION]
  4. OPTION
  5. -s, --srcFolder source folder path to be parsed. default: api
  6. -d, --dstFolder destination folder path storing automatically generated go files. default: internal/controller
  7. -w, --watchFile used in file watcher, it re-generates go files only if given file is under srcFolder
  8. -k, --sdkPath also generate SDK go files for api definitions to specified directory
  9. -v, --sdkStdVersion use standard version prefix for generated sdk request path
  10. -n, --sdkNoV1 do not add version suffix for interface module name if version is v1
  11. -c, --clear auto delete generated and unimplemented controller go files if api definitions are missing
  12. -m, --merge generate all controller files into one go file by name of api definition source go file
  13. -h, --help more information about this command
  14. EXAMPLE
  15. gf gen ctrl

Controller Generating - 图3tip

If using the project’s recommended framework scaffolding and make tool is installed, make ctrl shortcut can also be used.

Parameter explanation:

NameRequiredDefault ValueMeaning
srcFolderNoapiPoints to the directory address of api API definition files
dstFolderNointernal/controllerPoints to the directory where the generated controller files are stored
watchFileNoUsed in IDE file monitoring, for automatic generation when files change
sdkPathNoIf HTTP SDK needs to be generated, this parameter specifies the directory path for storing generated SDK code
sdkStdVersionNofalseWhether the generated HTTP SDK uses standard version management. It will automatically add a version routing prefix according to the API version. For example, v1 version API will have a /api/v1 request routing prefix added automatically.
sdkNoV1NofalseIn the generated HTTP SDK, whether the interface module name should not have the V1 suffix when the interface is version v1.
clearNofalseWhether to delete generated controller interface files in internal/controller when corresponding api layer definitions don’t exist.
mergeNofalseControls whether to generate ctrl controller code files according to API layer files rather than splitting API interfaces into different implementation files by default.

If using GolandIDE, the provided configuration file, watchers.xml, can be used for automatically generating interface files when code file modifications are detected. The usage is shown in the image below:

Controller Generating - 图4

Usage Example

Automatically generated API definition files

Controller Generating - 图5

Automatically generated controller code files

Controller Generating - 图6

Controller Generating - 图7

Automatically generated HTTP SDK code files

Controller Generating - 图8

Controller Generating - 图9

FAQ

Why does each api interface generate a controller file instead of merging into one controller file?

Controller Generating - 图10

For small or personal simple projects, or projects with only a few interfaces in an api module, this management style might not be an issue, and code files can be maintained according to personal preference. Here, we describe the scenario for more complex business projects or enterprise-level projects where an api module has many interfaces.

  • First, when developing api interfaces, locating api interface implementation is clearer and not about searching through a thousand lines of code in a file.

  • Moreover, in a collaborative project, if multiple people modify the same controller file, file conflicts easily arise in version management. Maintaining one api interface with a corresponding controller implementation file can minimize file conflict probabilities during collaboration, as most developers prefer not to waste valuable time resolving file conflicts again and again.

  • Finally, the controller layer code has its own responsibilities:

    • Validate input parameters: Client-submitted parameters are not trusted and usually require data validation in most scenarios.
    • Implement the interface logic: Either directly implement the interface logic in the controller or call one or more service interfaces or third-party service interfaces to implement the logic. Avoid implementing api interface logic in service layers as api interfaces are tied to specific business scenarios and are not reusable. 💀 A common mistake is directly passing the request through the controller to the service interface, making the controller seemingly redundant and the service layer’s implementation more cumbersome and non-reusable. 💀
    • Generate return data: Organize internal result data and generate the returning data API definition.
  • These responsibilities imply that controller code is also relatively complex. Maintaining them separately can alleviate developer mental burden and facilitate clear maintenance of api interface logic.

Some Suggestions:

If there are too many interface files in an api module, consider further splitting complex api modules into sub-modules. This can decouple complex api modules, and maintaining api API definitions and controller interface implementation files through multiple directories will make the structure clearer and facilitate better collaboration and version management.

After reviewing the design, if you still prefer managing all interfaces using a single source file, consider the merge parameter.

Why is there an empty go file in the corresponding controller module generated from the api module?

For Example:

Controller Generating - 图11

Explanation:

Each api module generates an empty go file under the module’s controller. This file is generated only once, allowing users to fill in necessary pre-defined code content, such as internal variable definitions, constants, data structures, or package initialization init method definitions, etc., within that module controller. We advocate for good code management practices, suggesting module pre-defined content should be consolidated in the module-named go file (module.go) rather than scattered across different go files, to better maintain the code.

If there is currently no need for custom code content in the controller, just leave the file empty for future extensions.