在了解了项目结构后,会明白我们往往会在Module后放入用户的功能,但是不同的功能实现涉及不同的理念,在小项目的时候,往往就是一坨功能合在一起,但是功能多起来了的时候,应该怎么实现?
先看看我一开始的代码:
1 2 3 4 5 6 7 8
| func main(){ r := gin.Default() log.Init() configs.Init() db.Init() routers.RootPath(r) }
|
1 2 3 4 5 6 7
| func RootPath(r *gin.Engine){ rootPath := r.Group("/user"){ r.POST("/register",Register) r.POST("/update",middleware.Auth(),Update) } }
|
1 2 3
| update.go register.go...
|
学习了NX的模板,才发现自己以前写功能实现就是一坨
NX的模板进行了更好的封装以及通用化处理
下面先看一下结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| |-cmd |-server |-server.go |-internal |-module |-user.go |-login.go |-init.go |-routers.go |-update.go |-login.go |-read.go |- 其他的包 --实现其他的功能 |-module.go |-main.go
|
1 2 3 4 5
| func main(){ server.Init() server.Run() }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| func Init(){ configs.Init() db.Init() for _ , m:=range Module{ fmt.Println("Init Module:" + m.GetName()) m.Init() } }
func Run(){ r := gin.New() r.use(log.Init(),middleware.Recovery()) for _,m:=range module.Module{ fmt.Printlun("InitRouter: "+m.GetName()) m.InitRouter(r.Group("/"+m.GetName())) } }
|
功能的NX实现来了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
func Module interface{}{ GetName()string Init() InitRouter(r *gin.RouterGroup) }
var Modules []Module
func RegisterModule(m Module){ Modules = append(Modules,m) }
func init(){ RegisterModule(&user.ModuleUser{}) }
|
GetName()实现了吧这个包的name传给了对应的r.Group
1 2 3 4 5 6 7 8 9
|
type ModuleUser struct{}
func (u *ModuleUser)GetName() string{ return "user" }
func (u *ModuleUser)Init(){}
|
对于空接口来说,什么类型都能够传入
对于有方法的接口来说,那么实现了其全部方法的类型就能够传入
所以可以吧 type ModuleUser struct{} 定义,只要ModuleUser实现了三个方法Init/InitRouter/GetName
1 2 3 4 5 6 7 8
| func (u *ModuleUser) InitRouter(r *gin.RouterGroup){ r.POST("/register",Register) r.POST("/login", Login) r.PUT("/update", middleware.Auth(), Update) r.GET("/read", middleware.Auth(), Read) r.DELETE("/delete", middleware.Auth(), Delete) }
|
神奇,能够发现的是真正好的代码往往使用方法接口的方式实现封装,在层层的封装下,实现通用化,在新增一个功能的情况下,只要专注于相应的功能实现,其他包中的Init实现都可以照抄
类似于,一坨shi山,以前的我新增一个功能相当于直接一坨扔进去,而NX相当于把一坨一点点涂上去,太优雅了。