golang基于Go类型生成任意代码及类型转换器插件库copygen的使用
Golang基于Go类型生成任意代码及类型转换器插件库Copygen的使用
Copygen是一个命令行和程序化的代码生成器,可以生成基于类型的自定义代码,包括类型到类型和字段到字段的代码,而无需向项目添加任何反射或依赖项。
什么是Copygen?
Copygen是一个基于类型的代码生成器,可以避免编写重复代码而浪费时间。它支持所有Go类型,包括basic
、array
、slice
、map
、chan
、interface
和func
类型。
如何使用Copygen?
步骤1. 定义Go类型
在文件中定义Go类型。
./domain/domain.go
// Package domain包含业务逻辑模型。
package domain
// Account表示用户账户。
type Account struct {
ID int
UserID string
Name string
Other string // 其他字段未使用。
}
./models/model.go
// Package models包含数据存储模型(如数据库)。
package models
// Account表示账户的数据模型。
type Account struct {
ID int
Name string
Password string
Email string
}
// User表示用户的数据模型。
type User struct {
UserID int
Name string
UserData string
}
步骤2. 配置设置文件
使用YML
和GO
文件设置Copygen。
setup.yml
# 定义代码生成的位置。
generated:
setup: ./setup.go
output: ../copygen.go
# 定义用于生成文件的可选自定义模板(支持.go、.tmpl)。
# template: ./generate.go
# 定义自定义选项(传递给生成器选项)以进行自定义。
custom:
option: 可能性是无限的。
setup.go
/* 指定生成文件的包名。 */
package copygen
/* Copygen定义了生成的函数。 */
type Copygen interface {
// custom 查看下表获取选项
ModelsToDomain(*models.Account, *models.User) *domain.Account
}
步骤3. 使用命令行
安装命令行工具Copygen:
go install github.com/switchupcb/copygen@latest
运行可执行文件:
copygen -yml path/to/yml
输出示例
生成的copygen.go
文件:
// Code generated by github.com/switchupcb/copygen
// DO NOT EDIT.
// Package copygen包含copygen生成代码的设置信息。
package copygen
import (
c "strconv"
"github.com/switchupcb/copygen/examples/main/domain"
"github.com/switchupcb/copygen/examples/main/models"
)
// Itoa将整数转换为ASCII值。
func Itoa(i int) string {
return c.Itoa(i)
}
// ModelsToDomain将*models.Account、*models.User复制到*domain.Account。
func ModelsToDomain(tA *domain.Account, fA *models.Account, fU *models.User) {
// *domain.Account字段
tA.ID = fA.ID
tA.UserID = Itoa(fU.UserID)
tA.Name = fA.Name
}
自定义选项
Copygen提供了多种选项来自定义代码生成:
选项 | 用途 | 描述 | 示例 |
---|---|---|---|
automatch field |
选择性使用自动匹配器 | 使用map 或tag 会禁用默认自动匹配器 |
automatch package.Type.Field |
map from to |
手动映射字段 | 将字段相互映射 | map models.Account.ID domain.Account.ID |
tag field key |
使用结构标签映射字段 | 使用标签键 | tag package.Type.Field key |
depth field level |
使用特定字段深度 | 覆盖默认深度 | depth models.Account.* 1 |
deepcopy field |
深度复制字段 | 默认浅拷贝 | deepcopy package.Type.Field |
custom option |
指定自定义函数选项 | 与模板一起使用 | ignore true |
转换和类型转换
使用convert function field
选项控制类型或字段在匹配时的复制方式:
/* 使用正则表达式定义此转换器应用的函数和字段。 */
// convert .* models.User.UserID
// Itoa将整数转换为ASCII值。
func Itoa(i int) string {
return c.Itoa(i)
}
使用场景
Copygen的默认目的是通过生成代码来映射对象,从而节省时间。典型使用场景包括:
- 在不同的模型类型(如
domain
和database
)之间转换 - 生成业务逻辑仓库包
- 为API请求生成包装函数
许可证
Copygen使用AGPLv3许可证。生成的代码可以不受限制地使用(包括专有和商业用途),但对Copygen软件源代码的修改或以编程方式在大型工作中实现Copygen需要遵守AGPLv3许可证。
完整示例Demo
以下是一个完整的示例,展示如何使用Copygen生成类型转换代码:
- 首先定义你的领域模型和数据模型(如上所示)
- 创建setup.yml和setup.go配置文件
- 运行Copygen生成代码
- 使用生成的函数进行类型转换
// 使用生成的函数
func main() {
// 创建模型实例
modelAcc := &models.Account{ID: 1, Name: "John"}
modelUser := &models.User{UserID: 123, Name: "Doe"}
// 转换为领域模型
domainAcc := ModelsToDomain(modelAcc, modelUser)
fmt.Printf("转换结果: %+v\n", domainAcc)
}
这个示例展示了如何轻松地在不同模型之间转换数据,而无需手动编写重复的赋值代码。
更多关于golang基于Go类型生成任意代码及类型转换器插件库copygen的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于Go类型生成任意代码及类型转换器插件库copygen的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用CopyGen生成Go代码和类型转换器
CopyGen是一个强大的Go代码生成工具,它可以基于现有类型自动生成代码,特别适合处理类型转换、DTO映射等重复性工作。
CopyGen基本使用
安装
go install github.com/switchupcb/copygen@latest
基本概念
CopyGen通过编写YAML配置文件来定义代码生成规则,然后基于这些规则生成Go代码。
示例:类型转换
假设我们有以下两个结构体:
// 用户数据库模型
type UserDB struct {
ID int
Username string
Email string
CreatedAt time.Time
}
// 用户API响应模型
type UserAPI struct {
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
}
1. 创建copygen.yml配置文件
# copygen.yml
generators:
user_converter:
output: ./gen/user_converter.go
package: gen
imports:
- "time"
functions:
- name: ConvertDBToAPI
from: UserDB
to: UserAPI
fields:
- from: ID
to: ID
transform: "strconv.Itoa(from)"
- from: Username
to: Username
- from: Email
to: Email
2. 运行CopyGen
copygen
3. 生成的代码
CopyGen会生成类似以下的代码:
// Code generated by copygen. DO NOT EDIT.
package gen
import (
"strconv"
"time"
)
// ConvertDBToAPI converts UserDB to UserAPI.
func ConvertDBToAPI(from UserDB) UserAPI {
return UserAPI{
ID: strconv.Itoa(from.ID),
Username: from.Username,
Email: from.Email,
}
}
高级用法
自定义转换函数
functions:
- name: ConvertDBToAPI
from: UserDB
to: UserAPI
fields:
- from: ID
to: ID
custom: "formatUserID(from.ID)"
然后在自定义模板中添加:
func formatUserID(id int) string {
return fmt.Sprintf("user_%d", id)
}
嵌套结构转换
对于嵌套结构,可以这样配置:
functions:
- name: ConvertOrderDBToAPI
from: OrderDB
to: OrderAPI
fields:
- from: User
to: User
function: ConvertDBToAPI
多个转换方向
functions:
- name: ConvertDBToAPI
from: UserDB
to: UserAPI
fields: [...]
- name: ConvertAPIToDB
from: UserAPI
to: UserDB
fields:
- from: ID
to: ID
transform: "strconv.Atoi(from)"
实际应用场景
- 数据库模型与API模型转换
- 不同版本API之间的兼容层
- 领域模型与持久化模型转换
- ProtoBuf/GRPC消息与内部模型转换
优势
- 类型安全:生成的代码是类型安全的,编译时就能发现错误
- 减少样板代码:自动生成重复的类型转换代码
- 易于维护:当模型变更时,只需重新生成代码
- 高性能:生成的代码是直接的赋值操作,没有反射开销
注意事项
- 生成的代码应该被检入版本控制
- 在CI流程中加入代码生成步骤,确保生成的代码是最新的
- 对于复杂转换逻辑,可以结合自定义函数使用
CopyGen通过自动化这些重复的模式转换工作,可以显著提高开发效率,同时减少人为错误的可能性。