sponge 本身支持自带模板生成代码,现在已开放基于自定义模板功能来生成代码,生成的代码类型和用途由你提供的模板代码(不局限于 go 代码)和参数决定。
1️⃣ 自定义模板 + 字段
基于自定义模板和字段生成代码是一种灵活且高效的方式。由于模板代码和字段完全由用户自定义,因此适合生成常用的可重复任意类型代码,例如web服务、gRPC服务、脚手架代码、配置文件 、编译或部署脚本等
创建自定义字段
自定义字段是模板生成代码的输入参数。首先,需要将字段名称和对应的值定义在一个 JSON 文件中,例如 fields.json
:
json
{
"ServerName": "web",
"PackageName": "main",
"HandlerName": "helloworld",
"Port": 8080
}
每个字段将对应模板代码中的占位符。
创建自定义模板代码
模板代码是代码生成的核心,基于 Go 的 text/template
库实现。因此,建议先熟悉其基本语法规则,语法规则很简单,几分钟即可熟悉。点击查看:Go text/template 基本语法规则。
创建模板文件时,可以使用固定文件名(如 main.go
)或变量文件名(如 {{.ServerName}}.go.tmpl
)。以下是一个示例模板文件内容:
go
package {{.PackageName}}
import (
"net/http"
)
// {{.HandlerName}} handles {{.HandlerName}} requests
func {{.HandlerName}}(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, world!"))
}
func main() {
http.HandleFunc("/{{.HandlerName}}", {{.HandlerName}})
if err := http.ListenAndServe(":{{.Port}}", nil); err != nil {
panic(err)
}
}
将模板文件存放在一个目录(如 template
)中,可以包含多个模板文件和子目录。
生成代码
使用 sponge 工具生成代码,以下是具体操作步骤:
- 打开 sponge 的 UI 界面;
- 进入左侧菜单栏 【自定义模板】 -> 【Field】;
- 填写以下参数(鼠标悬停在参数旁边的问号
?
上可以查看参数说明):- 自定义模板目录 :如
/template/web
- 自定义字段 :如
fields.json
- 自定义模板目录 :如
- 点击 下载代码 按钮,生成并下载代码,如下图所示:
等价命令 sponge template field --tpl-dir=/template/web --fields=fields.json
点击按钮查看模板信息
可以查看字段信息,这些字段信息对应模板的占位符,可以更方便的编写模板代码。
2️⃣ 自定义模板 + SQL + 字段
通过自定义模板和 SQL 的结合生成与表对应的代码(不局限于go代码)。只需提供 数据库连接信息 和 模板代码路径两个主要参数即可,支持多表批量生成代码。
适用场景:
- 后端 CRUD 相关代码(例如 api、router、service、dao、model等)。
- 前端 CRUD 相关的页面代码。
- 各种 ORM 的 CRUD 代码。
前期准备
sponge 目前支持数据库类型 mysql、mongodb、postgresql、sqlite。
下面以mysql为例,生成代码前准备:
- 已安装sponge
- mysql服务
- mysql表
生成代码需要依赖mysql服务和mysql表,这里有docker启动mysql服务脚本,启动mysql服务之后导入示例使用的库和表的sql。
打开终端,启动sponge UI界面服务:
bash
sponge run
在浏览器访问 http://localhost:24631 ,进入sponge生成代码的UI界面。
固定字段与自定义字段
代码生成功能支持两类字段:
- 固定字段
- 自定义字段
无论是固定字段还是自定义字段,每个字段都是对应模板代码中的占位符。
固定字段:是通过 SQL 自动解析出来不能更改的字段。一个表teacher对应的固定字段示例如下:
json
{
"TableColumnSubMessage": "",
"TableColumnSubStructure": {},
"TableColumns": [
{
"ColumnComment": "",
"ColumnName": "id",
"ColumnNameCamel": "ID",
"ColumnNameCamelFCL": "id",
"GoType": "uint64",
"IsPrimaryKey": true,
"Tag": ""
},
{
"ColumnComment": "用户名",
"ColumnName": "name",
"ColumnNameCamel": "Name",
"ColumnNameCamelFCL": "name",
"GoType": "string",
"IsPrimaryKey": false,
"Tag": ""
}
],
"DBDriver": "mysql",
"TablePrimaryKey": {
"GoType": "uint64",
"GoTypeFCU": "Uint64",
"IsStringType": false,
"Name": "id",
"NameCamel": "ID",
"NameCamelFCL": "id",
"NamePluralCamel": "IDs",
"NamePluralCamelFCL": "ids"
},
"TableComment": "老师",
"TableName": "teacher",
"TableNameCamel": "Teacher",
"TableNameCamelFCL": "teacher",
"TableNamePluralCamel": "Teachers",
"TableNamePluralCamelFCL": "teachers",
"TableNamePrefix": ""
}
自定义字段 :自定义字段是可选的,当模板需要时才将自定义字段定义在一个 JSON 文件中。例如,创建一个名为 fields.json
的文件,其内容如下:
json
{
"ModuleName": "user",
"PackageName": "handler",
"ServerName": "web",
"Port": 8080
}
在自定义字段中,请避免使用下面字段名称,因为它与固定字段的名称冲突。
DBDriver TablePrimaryKey TableNamePrefix TableName TableNameCamel TableNameCamelFCL TableNamePluralCamel TableNamePluralCamelFCL TableNameSnake TableComment TableColumns TableColumnSubStructure TableColumnSubMessage
创建自定义模板代码
模板代码是代码生成的核心,基于 Go 的 text/template
库实现。因此,建议先熟悉其基本语法规则,语法规则很简单,几分钟即可熟悉。点击查看:Go text/template 基本语法规则。
模板文件名建议使用变量(如 {{.TableNameCamelFCL}}.go.tmpl
),以避免多表批量生成时的文件名冲突。以下为一个自定义 CRUD 模板代码的示例:
go
package {{.PackageName}}
import (
"net/http"
"github.com/gorilla/mux"
)
type {{.TableNameCamelFCL}}Handler struct {}
func (h *{{.TableNameCamelFCL}}Handler) Create{{.TableNameCamel}}(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("{{.TableName}} created"))
}
func (h *{{.TableNameCamelFCL}}Handler) Delete{{.TableNameCamel}}By{{.PrimaryKey.NameCamel}}(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("{{.TableName}} deleted"))
}
func (h *{{.TableNameCamelFCL}}Handler) Update{{.TableNameCamel}}By{{.PrimaryKey.NameCamel}}(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("{{.TableName}} updated"))
}
func (h *{{.TableNameCamelFCL}}Handler) Get{{.TableNameCamel}}By{{.PrimaryKey.NameCamel}}(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("{{.TableName}} found"))
}
func (h *{{.TableNameCamelFCL}}Handler) List{{.TableNameCamel}}(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("List of {{.TableName}}"))
}
func Register{{.TableNameCamel}}Routes(r *mux.Router) {
r.HandleFunc("/{{.TableNameCamelFCL}}", Create{{.TableNameCamel}}).Methods("POST")
r.HandleFunc("/{{.TableNameCamelFCL}}/{ {{.PrimaryKey.Name}} }", Delete{{.TableNameCamel}}By{{.PrimaryKey.NameCamel}}).Methods("DELETE")
r.HandleFunc("/{{.TableNameCamelFCL}}/{ {{.PrimaryKey.Name}} }", Update{{.TableNameCamel}}By{{.PrimaryKey.NameCamel}}).Methods("PUT")
r.HandleFunc("/{{.TableNameCamelFCL}}/{ {{.PrimaryKey.Name}} }", Get{{.TableNameCamel}}By{{.PrimaryKey.NameCamel}}).Methods("GET")
r.HandleFunc("/{{.TableNameCamelFCL}}", List{{.TableNameCamel}}).Methods("GET")
}
将模板文件存放在一个目录(如 template
)中,可以包含多个模板文件和子目录。
生成代码
使用 sponge 的 UI 界面生成代码,具体步骤如下:
-
打开 sponge 的 UI 界面;
-
进入左侧菜单栏 【自定义模板】 -> 【SQL】;
-
填写以下参数(鼠标悬停在参数旁边的问号
?
上可以查看参数说明):- 数据库类型 :如
mysql
- 数据库 DSN :如
root:123456@(127.0.0.1:3306)/testdb
- 点击 获取表名,选择一个或多个表;
- 模板目录路径 :如
/template/api/crud
; - 自定义字段 JSON 文件 (可选):如
fields.json
。
- 数据库类型 :如
-
点击 下载代码 按钮,生成代码,如下图所示:
等价命令 sponge template sql --db-driver=mysql --db-dsn=root:123456@(192.168.3.37:3306)/account --db-table=user --tpl-dir=/template/api/crud --fields=fields.json
点击按钮查看模板信息
可以查看字段信息,这些字段信息对应模板的占位符,可以更方便的编写模板代码。
3️⃣ 自定义模板 + Protobuf + 字段
通过自定义模板和 Protobuf 可以用来生成各类自定义场景代码。只需提供 proto 文件 和 模板目录路径 两个主要参数即可,支持指定多个 proto 文件批量生成代码。
适用场景:
- gRPC service 代码。
- gRPC服务端和客户端的测试用例。
- http服务 api、router、service 等代码。
前期准备
在开始之前,请确保以下事项:
- 安装 sponge。
- 准备proto文件,如果proto文件有依赖其他proto文件,把依赖的proto文件存放在一个单独目录中。
打开终端,启动sponge UI界面服务:
bash
sponge run
在浏览器访问 http://localhost:24631 ,进入sponge生成代码的UI界面。
以下是一个 user.proto
的 Protobuf 文件示例,内容如下:
protobuf
syntax = "proto3";
package api.user.v1;
import "google/api/annotations.proto";
import "validate/validate.proto";
option go_package = "user/api/user/v1;v1";
service User {
// 登录
rpc Login(LoginRequest) returns (LoginReply) {
option (google.api.http) = {
post: "/api/v1/auth/login"
body: "*"
};
}
}
message LoginRequest {
string email = 1 [(validate.rules).string.email = true];
string password = 2 [(validate.rules).string.min_len = 6];
}
message LoginReply {
uint64 id = 1;
string token = 2;
}
固定字段与自定义字段
代码生成功能支持两类字段:
- 固定字段
- 自定义字段
无论是固定字段还是自定义字段,每个字段都是对应模板代码中的占位符。
固定字段:是通过 protobuf 自动解析出来不能更改的字段。一个 user.proto 对应的固定字段示例如下:
json
{
"Proto": {
"FileDir": "api/user/v1",
"FileName": "user.proto",
"FileNamePrefix": "user",
"FileNamePrefixCamel": "User",
"GoPackage": "\"user/api/user/v1\"",
"GoPkgName": "userV1",
"ImportPkgMap": {
"userV1": "userV1 \"user/api/user/v1\""
},
"FieldImportPkgMap": {
"userV1": "userV1 \"user/api/user/v1\""
},
"Package": "api.user.v1",
"Services": [
{
"GoPkgName": "userV1",
"Methods": [
{
"Comment": "// Login",
"HTTPRequestBody": "",
"HTTPRequestMethod": "POST",
"HTTPRouter": "/api/v1/auth/login",
"InvokeType": "unary_call",
"IsIgnoreGinBind": false,
"IsPassGinContext": false,
"MethodName": "Login",
"ReplyFields": [
{
"Comment": "",
"FieldType": "uint64",
"GoType": "uint64",
"GoTypeCrossPkg": "uint64",
"ImportPkgName": "",
"ImportPkgPath": "",
"Name": "Id"
}
],
"ReplyImportPkgName": "userV1",
"ReplyName": "LoginReply",
"RequestFields": [
{
"Comment": "",
"FieldType": "string",
"GoType": "string",
"GoTypeCrossPkg": "string",
"ImportPkgName": "",
"ImportPkgPath": "",
"Name": "Email"
}
],
"RequestImportPkgName": "userV1",
"RequestName": "LoginRequest"
}
],
"ServiceName": "User",
"ServiceNameCamel": "User",
"ServiceNameCamelFCL": "user",
"ServiceNamePluralCamel": "Users",
"ServiceNamePluralCamelFCL": "users"
}
]
}
}
自定义字段 :自定义字段是可选的,当模板需要时才将自定义字段定义在一个 JSON 文件中。例如,创建一个名为 fields.json
的文件,其内容如下:
json
{
"ModuleName": "user",
"PackageName": "service",
"ServerName": "grpc",
"Port": 8282
}
在自定义字段中,请避免使用
Proto
作为字段名,因为它与固定字段的名称冲突。
创建自定义模板代码
模板代码是代码生成的核心,基于 Go 的 text/template
库实现。因此,建议先熟悉其基本语法规则,语法规则很简单,几分钟即可熟悉。点击查看:Go text/template 基本语法规则。
模板文件名应使用变量形式(如 {{.Proto.FileNamePrefix}}.go.tmpl
),以避免处理多个 proto 文件时的命名冲突。以下是一个 gRPC 服务模板的示例:
go
package service
import (
"context"
"google.golang.org/grpc"
{{- range $pkgName, $pkgPath := .Proto.ImportPkgMap }}
{{$pkgPath}}
{{- end }}
)
// 注册 gRPC 服务
func Register{{.Proto.FileNamePrefixCamel}}Server(server *grpc.Server) {
{{- range .Proto.Services }}
{{.GoPkgName}}.Register{{.ServiceNameCamel}}Server(server, New{{.ServiceNameCamel}}Server())
{{- end }}
}
{{- range .Proto.Services }}
type {{.ServiceNameCamelFCL}} struct {
{{.GoPkgName}}.Unimplemented{{.ServiceNameCamel}}Server
}
// 创建服务实例
func New{{.ServiceNameCamel}}Server() {{.GoPkgName}}.{{.ServiceNameCamel}}Server {
return &{{.ServiceNameCamelFCL}}{}
}
{{- range .Methods }}
// {{.Comment}}
func (s *{{.ServiceNameCamelFCL}}) {{.MethodName}}(ctx context.Context, req *{{.RequestImportPkgName}}.{{.RequestName}}) (*{{.ReplyImportPkgName}}.{{.ReplyName}}, error) {
return &{{.ReplyImportPkgName}}.{{.ReplyName}}{}, nil
}
{{- end }}
{{- end }}
将模板文件存放在一个目录(如 template
)中,可以包含多个模板文件和子目录。
生成代码
在 sponge 的 UI 界面中操作,具体步骤如下:
- 进入界面 :点击左侧菜单 【自定义模板】 -> 【Protobuf】。
- 填写参数 (鼠标悬停在参数旁边的问号
?
上可以查看参数说明):- 模板目录路径:如
/template/grpc/service
- proto 文件路径:如
user.proto
- 依赖 proto 文件目录(可选):指定其他需要导入的 Protobuf 文件目录。
- 自定义字段 JSON 文件(可选):如
fields.json
。
- 模板目录路径:如
- 点击 下载代码 按钮,生成代码,如下图所示:
等价命令 sponge template protobuf --tpl-dir=/template/grpc/service --proto-file=user.proto --fields=fields.json
点击按钮查看模板信息
可以查看字段信息,这些字段信息对应模板的占位符,可以更方便的编写模板代码。
总结
Sponge 代码生成工具提供了灵活且高效的代码生成方式,支持以下三种生成模式:
- 自定义模板 + 字段
- 自定义模板 + SQL + 字段
- 自定义模板 + Protobuf + 字段
工具优势:
- 灵活性: 支持用户自定义模板,适用于各种编程语言和框架。
- 高效性:一键生成批量代码,大幅提高开发效率,减少重复性工作。
- 可扩展性: 支持多种数据源(SQL、Protobuf)及模板,满足不同开发需求。
- 可视化界面:通过 UI 配置自定义模板和字段,提供直观操作体验。
适用人群:
- 希望快速生成脚手架代码的开发者。
- 频繁需要重复性代码生成的团队。
- 对模板引擎和自动化工具感兴趣的技术爱好者。
通过 Sponge,你可以轻松定制代码生成方案,从而更专注于核心逻辑的开发。
Sponge gitHub 仓库 github.com/zhufuyi/spo...