Custom Scaffold Template
Kitex provides the ability to customize templates, if the default templates can not meet your needs, you can use the function of this custom template provided by Kitex. Now, it supports rendering single file and circular rendering according to methodInfo.
How to Use
-
The data used by the template is
PackageInfo
and we assume that this section contains all the metadata(e.g.methodInfo
…). You only need to pass the template file, and the data in the template isPackageInfo
data. -
Template rendering can only render a single file at a time. If there is a situation of sorting the file by
methods
and rendering it, you need to control them in your code. -
Templates are passed via the YAML folder and specified with the
--template-dir
command-line parameter. To avoid large files, templates are now organized into a dedicated directory. -
extensions.yaml
in the YAML folder is a specific file. The content of this configuration file is extending the service code. If it exists, there is no need to pass the ‘template-extension’ parameter. -
There are currently four update options available: overwrite, skip, append or add files based on specified methods (
loop_method
is true). The behavior is determined by thekey
field inupdate_behavior
, which can beskip
,cover
orappend
. Whenloop_method
is enabled,append
adds new files; otherwise, it appends to the end of the file, and the specifiedkey
during the update determines the behavior. -
The code generated by Kitex is divided into two parts, ‘kitex_gen’ and ‘mainPkg’ (including ‘main.go’, ‘handler.go’ …). ‘kitex_gen’ is immutable. Choosing between ‘mainPkg’ and ‘custom layout’ is a binary decision; specifying a ‘custom layout’ will prevent the generation of ‘mainPkg’.
Usage Scenarios
The default templates can not meet your needs. (e.g. want to generate ‘MVC Layout’,uniform error handling …)
Practice
kitex -module ${module_name} -template-dir ${template dir_path} idl/hello.thrift
YAML File
path: /a/main.go # specifies the path and name to the file. It will create the 'a' folder and 'main.go' file in the 'a' folder
update_behavior:
type: skip / cover / append # specifies the update behavior, if 'loop_methor' is true, append is not supported.the default value is skip
key: Test{{.Name}} # function name
append_tpl: # the new tpl
import_tpl: # the new import, it is a list and it can be rendered. Each item in the list supports rendering multiple imports in a loop, separated by spaces, such as: "\"a/b/c\" \"d/e/f\""
body: template content # tql content
--------------------------------
path: /handler/{{ .Name }}.go # The path will first undergo template rendering. If loop_service and loop_method are specified, it will be loop rendered. The data used for rendering is the current rendered single service (method).
update_is_skip: true # whether to skip this file when updating
loop_method: true # loop rendering supports method
loop_service: true # Multiple service support: If the "combine-service" command is set in the generation command and "loop_service: true" is specified in the template, the corresponding template file will be rendered in a loop according to the service during generation. It is the same format as loop_method, and will use the current template to loop render each service. It can be used simultaneously with loop_method.
body: ... # tql content
e.g. tql
https://github.com/cloudwego/cwgo/tree/main/tpl/kitex
Appendix
PackageInfo struct and some commonly used contents
type PackageInfo struct {
Namespace string // idl namespace, It is recommended not to use under pb
Dependencies map[string]string // package name => import path, used for searching imports
*ServiceInfo // the target service
Codec string
NoFastAPI bool
Version string
RealServiceName string
Imports map[string]map[string]bool
ExternalKitexGen string
Features []feature
FrugalPretouch bool
Module string // go module name
}
type ServiceInfo struct {
PkgInfo
ServiceName string
RawServiceName string
ServiceTypeName func() string
Base *ServiceInfo
Methods []*MethodInfo
CombineServices []*ServiceInfo
HasStreaming bool
}
type PkgInfo struct {
PkgName string // the last paragraph of of namespace
PkgRefName string
ImportPath string // this method's req and resp's import path
}
type MethodInfo struct {
PkgInfo
ServiceName string // this service's name
Name string // this method's name
RawName string // ditto
Oneway bool
Void bool
Args []*Parameter // params' info, including name, import path, and type
Resp *Parameter // response, including name, import path, and type
Exceptions []*Parameter
ArgStructName string
ResStructName string
IsResponseNeedRedirect bool // int -> int*
GenArgResultStruct bool
ClientStreaming bool
ServerStreaming bool
}
// Parameter
type Parameter struct {
Deps []PkgInfo
Name string
RawName string // StructB
Type string // *PkgA.StructB
}