昭通昭阳区城乡建设管理局网站,网站规划与建设实验心得体会,开个小网站要怎么做的,个人主页生成某个项目里有一段老代码写的不是很好#xff0c;想着能否通过自己掌握的知识#xff0c;将其改善一下。感兴趣的小伙伴可以通过了解背景和需求#xff0c;自己试想下该如何实现#xff0c;如果有更好的方案也欢迎留言讨论。
1. 背景及需求
(1) 背景
假设我们的下游提供了…某个项目里有一段老代码写的不是很好想着能否通过自己掌握的知识将其改善一下。感兴趣的小伙伴可以通过了解背景和需求自己试想下该如何实现如果有更好的方案也欢迎留言讨论。
1. 背景及需求
(1) 背景
假设我们的下游提供了一个定时任务接口CronJob(cron string, fun func())它的入参有两个分别是定时任务执行的频率以及具体执行哪个函数。我们要借助该定时任务接口实现一个功能对数据库中同一张表的所有数据的两个不同的字段完成赋值。为了给每个字段赋值会分别设置两个定时任务一个是正常的任务处理5分钟执行一次负责捞取最近30分钟的数据并完成赋值。另一个是补偿的任务处理1小时执行一次负责捞取最近24小时的数据并完成赋值。
(2) 需求
代码的实现要满足以下要求
因为都是捞取同一张表的数据并完成赋值所以该部分代码应该复用同一份代码防止出错后续可能有新增字段需要类似的赋值逻辑所以代码应该有良好的可扩展性由于只有字段赋值逻辑不同所以每次新增字段赋值需求时代码的改动应该尽可能小。
2. 需求分析及实现
(1) 定时任务代码
由于我们依赖下游的定时任务接口所以首先给出模拟的定时任务接口。
// CronJob 模拟定时任务参数分别为调度时间和调度内容
func CronJob(cron string, fun func()) {fmt.Println(调度时间: , cron)fmt.Println(定时任务执行开始。。。)fun()fmt.Println(定时任务执行结束。。。\n\n)
}(2) 定义接口
我们需要实现的是对字段的赋值方法由于同一字段的赋值分为了正常的任务处理和补偿的任务处理两个所以我们可以定义两个接口方法Common和Fix。
// ProcessJob 处理任务接口定义了两个方法
type ProcessJob interface {Common(name string) func() // 正常的任务处理Fix(name string) func() // 补偿的任务处理
}(3) 接口的实现类
定义了接口后接口的实现类应该分别实现上述两个方法完成两个字段的赋值逻辑。而从数据库捞取数据的部分显然是通用的该部分可以独立成为一个函数该函数可以捞取数据并将数据的主键id传参给实现类的两个方法完成该条数据的赋值。
1) 通用部分
正常和补偿任务处理中通用的部分
// Common 正常的任务处理中通用的部分
func Common(name string, fun func(params string)) func() {id : $模拟id$return func() {fmt.Println(任务名称为, name)fmt.Println(正常任务处理的前置操作。。。)fun(id)fmt.Println(正常任务处理的后置操作。。。)}
}// Fix 补偿的任务处理中通用的部分
func Fix(name string, fun func(params string)) func() {id : $模拟id$return func() {fmt.Println(任务名称为, name)fmt.Println(补偿任务处理的前置操作。。。)fun(id)fmt.Println(补偿任务处理的后置操作。。。)}
}注意下通用方法的入参这里分别用来接收实现类方法传入的参数以及字段赋值逻辑的函数。
2) 第一个接口实现类
第一个处理任务为第一个字段赋值
// ProcessJob1 第一个处理任务为第一个字段赋值
type ProcessJob1 struct{}// Common 第一个处理任务的正常任务处理
func (pj ProcessJob1) Common(name string) func() {return Common(name, func(id string) {fmt.Printf(常规任务处理中为id为 %v 的第一个字段进行赋值, id)})
}// Fix 第一个处理任务的补偿任务处理
func (pj ProcessJob1) Fix(name string) func() {return Fix(name, func(id string) {fmt.Printf(补偿任务处理中为id为 %v 的第一个字段进行赋值, id)})
}这里需要注意下由于定时任务接口只接受类型为func()的函数所以接口实现类的Common和Fix方法的返回值都是func()类型。而字段赋值逻辑函数的入参为从通用函数那传入的参数即数据的主键id。
3) 第二个接口实现类
第二个处理任务为第二个字段赋值
// ProcessJob2 第二个处理任务为第二个字段赋值
type ProcessJob2 struct{}// Common 第二个处理任务的正常任务处理
func (pj ProcessJob2) Common(name string) func() {return Common(name, func(id string) {fmt.Printf(常规任务处理中为id为 %v 的第二个字段进行赋值, id)})
}// Fix 第二个处理任务的补偿任务处理
func (pj ProcessJob2) Fix(name string) func() {return Fix(name, func(id string) {fmt.Printf(补偿任务处理中为id为 %v 的第二个字段进行赋值, id)})
}(4) 实现类再封装
由于ProcessJob1和ProcessJob2都可以看做是ProcessJob类型所以可以为实现类再封装一层以便统一进行处理。通过分析需求可以知道实现类的属性可以有任务名称、正常任务处理的调度时间、补偿任务处理的调度时间等组成所以可以定义以下类型
// JobConf 定时任务配置
type JobConf struct {Name string // 定时任务的名称CommonCron string // 正常任务处理的调度时间FixCron string // 补偿任务处理的调度时间ProcessJob ProcessJob // 处理任务对象
}(5) 添加/获取任务配置
定义了统一的类型之后就可以创建一个该类型的列表如果有新增的字段赋值需求那么就可以很方便的进行扩展了只需要在列表中新增一个任务配置即可。
// GetJobConfMap 获取所有的任务配置信息
func GetJobConfMap() map[string]JobConf {// 定义一个任务配置的列表如有新增的任务直接append一个新任务即可jobConfList : make([]JobConf, 0)jobConfList append(jobConfList, JobConf{Name: job1,CommonCron: 1 * * * * *,FixCron: 11 * * * * *,ProcessJob: ProcessJob1{},})jobConfList append(jobConfList, JobConf{Name: job2,CommonCron: 2 * * * * *,FixCron: 22 * * * * *,ProcessJob: ProcessJob2{},})// 获取任务名到任务配置的mapjobConfMap : make(map[string]JobConf)for _, jobConf : range jobConfList {jobConfMap[jobConf.Name] jobConf}return jobConfMap
}(6) 主函数
最后就是根据每个任务的配置启动对应的定时任务了。
func main() {// 获取所有的任务配置信息jobConfMap : GetJobConfMap()// 为每个任务独立设置调度时间以及处理内容for jobName, jobConf : range jobConfMap {processJob : jobConf.ProcessJobCronJob(jobConf.CommonCron, processJob.Common(jobName))CronJob(jobConf.FixCron, processJob.Fix(jobName))}
}3. 完整代码
package mainimport (fmt
)// CronJob 模拟定时任务参数分别为调度时间和调度内容
func CronJob(cron string, fun func()) {fmt.Println(调度时间: , cron)fmt.Println(定时任务执行开始。。。)fun()fmt.Println(定时任务执行结束。。。\n\n)
}// ProcessJob 处理任务接口定义了两个方法
type ProcessJob interface {Common(name string) func() // 正常的任务处理Fix(name string) func() // 补偿的任务处理
}// Common 正常的任务处理中通用的部分
func Common(name string, fun func(params string)) func() {id : $模拟id$return func() {fmt.Println(任务名称为, name)fmt.Println(正常任务处理的前置操作。。。)fun(id)fmt.Println(正常任务处理的后置操作。。。)}
}// Fix 补偿的任务处理中通用的部分
func Fix(name string, fun func(params string)) func() {id : $模拟id$return func() {fmt.Println(任务名称为, name)fmt.Println(补偿任务处理的前置操作。。。)fun(id)fmt.Println(补偿任务处理的后置操作。。。)}
}// JobConf 定时任务配置
type JobConf struct {Name string // 定时任务的名称CommonCron string // 正常任务处理的调度时间FixCron string // 补偿任务处理的调度时间ProcessJob ProcessJob // 处理任务对象
}// ProcessJob1 第一个处理任务为第一个字段赋值
type ProcessJob1 struct{}// Common 第一个处理任务的正常任务处理
func (pj ProcessJob1) Common(name string) func() {return Common(name, func(id string) {fmt.Printf(常规任务处理中为id为 %v 的第一个字段进行赋值, id)})
}// Fix 第一个处理任务的补偿任务处理
func (pj ProcessJob1) Fix(name string) func() {return Fix(name, func(id string) {fmt.Printf(补偿任务处理中为id为 %v 的第一个字段进行赋值, id)})
}// ProcessJob2 第二个处理任务为第二个字段赋值
type ProcessJob2 struct{}// Common 第二个处理任务的正常任务处理
func (pj ProcessJob2) Common(name string) func() {return Common(name, func(id string) {fmt.Printf(常规任务处理中为id为 %v 的第二个字段进行赋值, id)})
}// Fix 第二个处理任务的补偿任务处理
func (pj ProcessJob2) Fix(name string) func() {return Fix(name, func(id string) {fmt.Printf(补偿任务处理中为id为 %v 的第二个字段进行赋值, id)})
}// GetJobConfMap 获取所有的任务配置信息
func GetJobConfMap() map[string]JobConf {// 定义一个任务配置的列表如有新增的任务直接append一个新任务即可jobConfList : make([]JobConf, 0)jobConfList append(jobConfList, JobConf{Name: job1,CommonCron: 1 * * * * *,FixCron: 11 * * * * *,ProcessJob: ProcessJob1{},})jobConfList append(jobConfList, JobConf{Name: job2,CommonCron: 2 * * * * *,FixCron: 22 * * * * *,ProcessJob: ProcessJob2{},})// 获取任务名到任务配置的mapjobConfMap : make(map[string]JobConf)for _, jobConf : range jobConfList {jobConfMap[jobConf.Name] jobConf}return jobConfMap
}func main() {// 获取所有的任务配置信息jobConfMap : GetJobConfMap()// 为每个任务独立设置调度时间以及处理内容for jobName, jobConf : range jobConfMap {processJob : jobConf.ProcessJobCronJob(jobConf.CommonCron, processJob.Common(jobName))CronJob(jobConf.FixCron, processJob.Fix(jobName))}
}