内容简介:本文首发于我的博客: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企业建站源代码解密工具,适用于纯本地解密机制!
- 创业公司的经济适用架构师
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
SOA & Web 2.0 -- 新商业语言
(美)Sandy Carter / 袁月杨、麻丽莉 / 清华大学出版社 / 2007 / 29.80元
在《SOA&Web 2.0:新商业语言》中,Sandy Calter示范了将企业解构为“组件化”业务模式的方法,然后用相互连接的、可重复的并且能快速、轻松、经济地适应各种变化的IT服务来支持该模式。这些技术将帮助IT专家和业务经理达到崭新的运营水平,以开展着眼于市场的创新,这才是最重要的。总而言之,企业必须实现灵活应对。直到最近,技术都一直阻碍着这些目标的实现。正是由于面向服务架构(SOA)、We......一起来看看 《SOA & Web 2.0 -- 新商业语言》 这本书的介绍吧!
RGB转16进制工具
RGB HEX 互转工具
UNIX 时间戳转换
UNIX 时间戳转换