Go 编程:routine, 这个压箱底的库推荐一下

Go 编程:routine, 这个压箱底的库推荐一下主要功能其实都已经在 routine 中实现了, job 其实只是做了一个简单的组装而已。当然,job 项目中还用到了,我封装的另外一个库 cm

欢迎大家来到IT世界,在知识的湖畔探索吧!

以下文章来源于一艘慢船 ,作者一艘慢船

最近发现 job[1] 有很多 clone。这个写了快一年的项目当时的目的是为了做压力测试。

现在回看整个项目与代码都存在太多的冗余,所以做了一下重构。重构之后的项目,全部代码也就 80 行左右。

主要功能其实都已经在 routine[2] 中实现了, job[3] 其实只是做了一个简单的组装而已。

所以,也就借着这次重构,向大家介绍一下,这个压箱底的库 routine[4]. 这个库自从写出来以后,基本上我所有的 Go 项目都会使用。

routine 做了什么

为什么要写这么一个基础库呢?

每段程序都是从 main 函数开始的,但是,却不会将整个程序的功能实现都放在 main 函数里。而是,通过层层功能的抽象与封装,最终,在 main 函数仅提供功能函数的入口。所以,当我们看很多大型程序时,其实,main 函数是非常简单的。

但是,即使 main 函数越变越简单,有些必要的功能则是逃不掉的。例如程序启动参数、程序的信号处理,这些通常还是会放在 main 函数进行处理。

除了以上 main 函数本身的处理以外,我发现将程序中的执行绪,也就是固定的 Go 协程的入口放在 main 函数中进行定义,可以帮助维护者更加快速的理解应用的逻辑实现。

所以,我就写了这样一个基础库,我只需要将具体的功能实现作为 Executor 接口的实现即可。使用起来就是这样:

package main

import (
 "log"
 "context"

 "github.com/x-mod/routine"
)

func main(){

    //功能实现
    YourExecutor := routine.Command("echo", routine.ARG("hello routine!"))

    //Main封装
 if err := routine.Main(
  context.TODO(),
        routine.Executor(YourExecutor),
        routine.Signal(syscall.SIGINT, routine.SigHandler(func() {
    os.Exit(1)
   })),
 ); err != nil {
  log.Fatal(err)
 }
}

欢迎大家来到IT世界,在知识的湖畔探索吧!

routine 协程控制

很多刚刚初级 Go 语言开发人员,常常在控制协程犯如下错误:

欢迎大家来到IT世界,在知识的湖畔探索吧!wg sync.WaitGroup

wg.Add(1) //! 正确写法
go func(){
    wg.Add(1) //! 错误写法
    defer wg.Done()
    ...
}()
wg.Wait()

提供一个简单协程控制的基础库,可以规避类似错误。

整个routine的协程逻辑可以通过下图进行一个简单的展示。

Go 编程:routine, 这个压箱底的库推荐一下

routine 执行器

routine 库除了提供一个 main 函数的基础框架与协程控制以外,还提供了很多功能函数的执行器。包括:

  • 重试执行 retry
  • 重复执行 repeat
  • 计划执行 crontab
  • 并发执行 concurrent

等等,很多功能性封装。

import "github.com/x-mod/routine"

//timeout
timeout := routine.Timeout(time.Minute, exec)

//retry
retry := routine.Retry(3, exec)

//repeat
repeat := routine.Repeat(10, time.Second, exec)

//concurrent
concurrent := routine.Concurrent(4, exec)

//schedule executor
crontab := routine.Crontab("* * * * *", exec)

//command
command := routine.Command("echo", routine.ARG("hello routine!"))

//parallel
parallel := routine.Parallel(exec1, exec2, exec3, ...)

//sequence
sequece := routine.Append(exec1, exec2, exec3, ...)

routine 实现 job

所以,有了 routine 库以后,重构job的功能,就非常简单,真的仅仅只是简单的组装代码而已了。

不妨看一下, job的核心代码:

欢迎大家来到IT世界,在知识的湖畔探索吧!func Main(c *cmd.Command, args []string) error {
 if len(args) == 0 {
  return fmt.Errorf("job command required")
 }
 cmdOpts := []routine.CommandOpt{}
 for index, argument := range args {
  if index >= 1 {
   cmdOpts = append(cmdOpts, routine.ARG(argument))
  }
 }
 command := routine.Executor(routine.Command(args[0], cmdOpts...))
 if viper.GetDuration("cmd-timeout") > 0 {
  command = routine.Timeout(viper.GetDuration("cmd-timeout"), command)
 }
 if viper.GetInt("retry") > 0 {
  command = routine.Retry(viper.GetInt("retry"), command)
 }
 if viper.GetInt("repeat-times") > 0 {
  command = routine.Repeat(
   viper.GetInt("repeat-times"),
   viper.GetDuration("repeat-interval"),
   command)
 }
 if viper.GetInt("concurrent") > 0 {
  command = routine.Concurrent(viper.GetInt("concurrent"), command)
 }
 if viper.GetDuration("job-timeout") > 0 {
  command = routine.Timeout(viper.GetDuration("job-timeout"), command)
 }
 if len(viper.GetString("schedule")) > 0 {
  command = routine.Crontab(viper.GetString("schedule"), command)
 }
 ctx, cancel := context.WithCancel(context.TODO())
 return routine.Main(
  ctx,
  command,
  routine.Signal(syscall.SIGINT, routine.SigHandler(func() {
   cancel()
  })),
 )
}

当然,job 项目中还用到了,我封装的另外一个库 cmd[5],通过这个库可以快速的实现一个命令行程序。感兴趣的同学不妨参考一下。

参考资料

[1]

job: https://github.com/liujianping/job

[2]

routine: https://github.com/x-mod/routine

[3]

job: https://github.com/liujianping/job

[4]

routine: https://github.com/x-mod/routine

[5]

cmd: https://github.com/x-mod/cmd

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/40819.html

(0)
上一篇 2024年 2月 23日 上午9:00
下一篇 2024年 3月 1日 下午4:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信