题目描述
golang下一个包内文件太多, func太多,用的时候不方便区分,
使用struct封装成PHP那种,再加加构造函数的,又怕影响性能.
题目来源及自己的思路
例如util包下有这么几个文件,以前的时候我会把不同func先归类到不同的文件,然后将文件单独放一个独立目录下作为一个包例如下面的math,common等都会单独放一个包里面.
像这样
util
├── math
└── math.go
├── common
└── common.go
├── cookie
└── cookie.go
├── encrypt
└── encrypt.go
├── fileutil
└── fileutil.go
├── json
└── json.go
但是这样感觉很麻烦,而且有的时候一个包下面难免会有多个文件,没法完全避免同一个包下很多个文件.
现在我直接把util的所有文件放一个目录下每个文件中使用struct封装起来,再搞一个构造函数,做分类.用的时候直接调用构造函数
但是这样感觉又会导致指针逃逸很影响GC性能. 尴尬啊
util
├── math.go
├── common.go
├── cookie.go
├── encrypt.go
├── fileutil
├── json.go
相关代码
例如下面的model, 因为数据库连接一般都放在同一个目录下,根据表名的不同,写到不同的文件.
如果不用struct封装起来,很多func会重名,用的时候很尴尬.封装起来的话,又怕影响性能.
package model
type UserModel struct {
}
func NewUserModel() *UserModel {
return &UserModel{} //出现指针逃逸
}
func (receiver UserModel) AddNew(user entity.User) (int64, error) {
if err := core.DB.Create(&user).Error; err != nil {
return 0, err
}
return user.ID, nil
}
func (receiver UserModel) GetInfoByMobile(mobile string) (t entity.User, err error) {
err = core.DB.Where("mobile=?", mobile).First(&t).Error
return
}
你期待的结果是什么?实际看到的错误信息又是什么?
求大佬们指点,包下面有多个文件和方法时,应该怎么做.
切忌盲目优化/过早优化,先分析瓶颈,再考虑解决。
对于工具函数一般就是聚合到一个包里,如果工具函数很多,再按用途分成多个子包,和你题中描述的一样:
但是你说:
实话说我不能理解 很麻烦 和 没法完全避免同一个包下很多个文件。
首先关于麻烦,工具包下要不要再分子包应该是经过权衡、认为一个包里存放所有工具函数已经不可接受,才分包管理,这是在难维护和用起来/写起来简单之间权衡。你说的麻烦可以再具体放到实际场景里去权衡,值不值得用这个“麻烦”去交换分包带来的好处。
其次没法避免很多个文件。go不是Java,也不是其他传统的“OOP”语言,从其他语言转go的话最好不要把其他语言的项目结构直接搬到go里,像是Java一个文件一个类,硬搬到go里一个struct一个go文件就有点迷惑了。
为什么要避免多个文件呢?数量真的很多,职责混乱,可以再分子包。数量很多但职责明确清晰,一个包里放多个go文件也不会有问题,都应该从实际出发。
项目目录结构组织上来说只要能满足几个点我觉得就完全ok。
具体到你的用户模型的场景里,我个人看法是:
关于优化,不是不建议优化,主要是:
一要相信编译器的优化能力;
二盲目优化的时间和脑力完全可以做更有价值的性能分析、调优或功能。web开发程序本身执行性能很少成为瓶颈,如果你们有做分析的话会发现绝大部分耗时都在数据查询和网络传输上。
像是你担心的Model结构逃逸,造成大量小对象gc的问题,go虽然有对象池可以用,但显然会增加你代码的复杂度和拖累可维护性。这又是一个tradeoff。考虑是不是Model结构的频繁创建导致的大量gc或者长gc?给Model加对象池能解决多少gc问题?后续项目维护中,新人能不能看懂用对象池的意图,会不会改坏,加上对象池之后接口用法是不是要变?
写太多了,不一定都对,可能有点掺杂了个人情绪发泄,见谅。
我自己总结下吧,省得抬杠: