内容简介:本文首发于我的博客:DTO (Data Transfer Object) 是Java中的概念,起到数据封装和隔离的作用。在使用Golang开发Web应用的过程中,也会有类似的需求。先贴项目地址现在有一个用户数据结构如下,
本文首发于我的博客: Golang适用的DTO工具 ,我同时在知乎专栏也发布了同样主题的文章,但是文章脉络更清晰一点(个人感觉),链接由此去 知乎版本-Golang适用的DTO工具 ,逃~
DTO (Data Transfer Object) 是 Java 中的概念,起到数据封装和隔离的作用。在使用Golang开发Web应用的过程中,也会有类似的需求。先贴项目地址 github.com/yeqown/server-common/tree/master/dbs/tools
举个例子
现在有一个用户数据结构如下,
type UserModel struct {
ID int64 `gorm:"column:id"`
Name string `gorm:"column:name"`
Password string `gorm:"column:password"`
}
// 问题1: 现在要求是想要JSON格式返回用户数据,并且不希望其中包含有Password字段
// 解决1:
type UserModel struct {
ID int64 `gorm:"column:id" json:"id"`
Name string `gorm:"column:name" json:"name"`
Password string `gorm:"column:password" json:"-"`
}
// 问题2: 同样是JSON数据格式,并且希望额外返回用户的身份标示Ident(假设必须要跟用户数据放在一起)
// 解决2: (这也是我的场景)
type UserDTO struct {
ID int64 `json:"id"`
Name string `json:"name"`
Password string `json:"-"`
Ident string `json:"ident"`
}
func LoadUserDTOFromModel(data *UserMolde) *UserDTO {
ident := genUserIdent(data)
return &{
ID data.ID,
Name data.Name,
Ident ident,
}
}
背景和需求
一般来说我的项目结构如下:其中models和services也就是分开定义Data struct(UserModel)和Object(UserDTO)的文件夹。
其实DTO的过程对于我来说,就是基于Data Struct生成一个新的Struct结构,并附带一个 func LoadDTOTypeFromModel(data *ModelType) *DTOType
。在这个过程中,其实除了个别Object结构体需要额外处理以外,大部分都是新换一个tag~。因此这部分工作步骤都是类似的,那么为什么不用一个 工具 来避免这部分重复的工作呢~?
思路
先说一下思路:
· 1. 从 .go
中获取到指定结构体的结构性描述
· 2. 根据结构性描述来生成新的结构体
· 3. 根据额外的配置,生成一个新的文件 types.go
其中结构性描述如下:
type innerStruct struct {
fields []*field
content string
name string
pkgName string
}
type field struct {
name string // field name string
typ string // field type string
tag string // tag name string
}
在整个流程中比较麻烦的就是,怎么获取到,特定类型结构体的结构性描述?。这里想记录一个小插曲:最开始我找解析 go 文件方法的时候,在Google中搜索“如何解析go文件”,出来的结果没有太大帮助,然后我又尝试了“How to parse .go file source code”,结果就提示了 parser
& loader
两个看起来就很有帮助的包名。。。。这里我选用了 loader
。
关于loader包的说明
Package loader loads a complete Go program from source code, parsing and type-checking the initial packages plus their transitive closure of dependencies.
正好这个包是从源代码去加载Go程序,对初始包进行解析和类型检查等。
Go文件解析部分
经过阅读loader包文档,我完成了一个函数用于获取指定的结构体的结构性描述信息: 代码在此
// Exported, and specified type
func loadGoFiles(dir string, filenames ...string) ([]*innerStruct, error) {
newFilenames := []string{}
for _, filename := range filenames {
newFilenames = append(newFilenames, path.Join(dir, filename))
}
conf.CreateFromFilenames("", newFilenames...)
prog, err := conf.Load()
if err != nil {
log.Println("load program err:", err)
return nil, err
}
return loopProgramCreated(prog.Created), nil
}
// loopProgramCreated to loo and filter:
// 1. unexported type
// 2. bultin types
// 3. only specified style struct name
func loopProgramCreated(
created []*loader.PackageInfo,
) (innerStructs []*innerStruct) {
for _, pkgInfo := range created {
pkgName := pkgInfo.Pkg.Name()
defs := pkgInfo.Defs
for indent, obj := range defs {
if !indent.IsExported() ||
obj == nil ||
!strings.HasSuffix(indent.Name, specifiedStructTypeSuffix) {
continue
}
// obj.String() 得到的string如:
// type testdata.UserModel struct{Name string "gorm:\"colunm:name\""; Password string "gorm:\"column:password\""}
is := parseStructString(obj.String())
is.pkgName = pkgName
is.pureName()
if isDebug {
log.Println("parse one Model: ", is.name, is.pkgName, is.content)
}
innerStructs = append(innerStructs, is)
}
}
return
}
其中 parseStructString
是对形如
type testdata.UserModel struct{Name string "gorm:"colunm:name""; Password string "gorm:"column:password""}
的字符串进行处理并整理成为 innerStruct
数据。
使用说明
go get github.com/yeqown/server-common/dbs/tools
# 获取 github.com/yeqown/server-common/tool.main.go,
# 并选择性的实现自己的 CustomParseTagFunc & CustomGenerateTagFunc
go build -o dbtools tool.main.go
➜ ✗ dbtools -h
Usage of ./dbtools:
-debug
调试模式开关,调试模式下会输出额外的信息
-dir string
指定需要解析的目录
-filename string
指定哪些文件需要被解析,如果未设置默认dir路径下所有的.go文件
-generateDir string
生成文件存放的目录,默认当前路径
-generateFilename string
生成文件名,默认"types.go"
-generatePkgName string
生成文件的包名,默认"types"
-generateStructSuffix string
替换model struct的后缀,默认无后缀,如UserSuffix => User
-modelImportPath string
指明model struct的导入路径, 如my-server/models
-modelStructSuffix string
指明特定后缀的model struct需要被解析,默认"Model"
工具测试结果
./bin/dbtools \ -dir=./dbs/tools/testdata \ -filename=type_model.go \ -generatePkgName=main \ -modelImportPath=github.com/yeqown/server-common/dbs/tools/testdata \
参考链接
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 26个适用于VMware管理员的强大工具
- 适用于物联网应用的强大数据可视化工具
- 自动生成高效DNN,适用于边缘设备的生成合成工具FermiNets
- DoraemonKit:一款适用于 iOS App 的线下测试工具集合
- CMSEasy企业建站源代码解密工具,适用于纯本地解密机制!
- 创业公司的经济适用架构师
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
PHP and MySQL Web Development
Luke Welling、Laura Thomson / Sams / July 25, 2007 / $49.99
Book Description PHP and MySQL Web Development teaches you to develop dynamic, secure, commerical Web sites. Using the same accessible, popular teaching style of the three previous editions, this b......一起来看看 《PHP and MySQL Web Development》 这本书的介绍吧!