Go语言(二十一) 常见的模块使用

时间:2022-07-25
本文章向大家介绍Go语言(二十一) 常见的模块使用,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

模块使用

执行系统shell命令

  • 使用os/exec模块
package main

import (
   "fmt"
   "os/exec"
)

func main()  {
   var (
      cmd *exec.Cmd
      err error
   )
   cmd = exec.Command("/bin/bash","-c","echo hello")
   err = cmd.Run()
   if err != nil {
      fmt.Println(err)
   }
   fmt.Println(err)
}
  • 获取命令执行的返回结果
package main

import (
   "fmt"
   "os/exec"
)

func main()  {
   var (
      cmd *exec.Cmd
      output []byte
      err error
   )
   //生成cmd
   cmd = exec.Command("/bin/bash","-c","sleep 1;ls -l ~/")
   if output,err = cmd.CombinedOutput();err != nil {
      fmt.Printf("cmd return faild,err:%vn",err)
      return
   }
   //打印返回结果
   fmt.Printf("%sn",string(output))
}
  • 多线程
package main

import (
   "context"
   "fmt"
   "os/exec"
   "time"
)

type result struct {
   err error
   output []byte
}

func main() {
   var (
      cmd *exec.Cmd
      ctx context.Context
      cancelFunc context.CancelFunc
      resultChan chan *result
      res *result
   )

   resultChan = make(chan *result,1000)   //创建一个结果队列
   ctx,cancelFunc = context.WithCancel(context.TODO())

   go func() {
      var (
         output []byte
         err error
      )
      cmd = exec.CommandContext(ctx,"/bin/bash","-c","sleep 2;echo hello")
      //执行任务,捕获输出
      output,err = cmd.CombinedOutput()
      //把输出结果输出给main协程
      resultChan <- &result{
         err:   err,
         output: output,
      }
   }()

   //1秒取消上下文
   time.Sleep(time.Second*3)
   //取消上下文
   cancelFunc()
   //在main协程里等待子协程的退出,并打印任务执行的结果
   res = <- resultChan
   fmt.Println(res.err,string(res.output))
   //fmt.Printf("err=%v,res=%sn",res.err,string(res.output))
}

cron模块的使用

  • 执行单个任务
package main

import (
   "fmt"
   "github.com/gorhill/cronexpr"
   "time"
)

func main() {
   var (
      expr *cronexpr.Expression
      err error
   )
   //每分钟执行一次
   /*
   if expr,err = cronexpr.Parse("* * * * *");err != nil {
      fmt.Println(err)
      return
   }
   */
   //每五秒执行一次,支持到年的配置
   if expr,err = cronexpr.Parse("*/5 * * * * * *");err != nil {
      fmt.Println(err)
      return
   }
   //获取当前时间
   now := time.Now()
   //下次执行时间
   nextTime := expr.Next(now)
   //等待这个定时器超时
   time.AfterFunc(nextTime.Sub(now), func() {
      fmt.Println("被调度了:",nextTime)
   })

   time.Sleep(time.Second*5)
}
  • 执行多个任务
package main

import (
   "fmt"
   "github.com/gorhill/cronexpr"
   "time"
)

type CronJob struct {
   expr *cronexpr.Expression
   nextTime time.Time
}

func main() {
   //需要一个调度协程,定时检查所有的cron任务,谁过期执行谁
   var (
      cronJob *CronJob
      expr *cronexpr.Expression
      now time.Time
      scheduleTable map[string]*CronJob
   )

   scheduleTable = make(map[string]*CronJob)    //初始化调度表
   //获取当前时间
   now = time.Now()
   // 1.定义两个cron
   expr = cronexpr.MustParse("*/5 * * * * * *")
   cronJob = &CronJob{
      expr:     expr,
      nextTime: expr.Next(now),
   }
   //将任务1注册到调度表
   scheduleTable["job1"] = cronJob
   // 2.定义两个cron
   expr = cronexpr.MustParse("*/5 * * * * * *")
   cronJob = &CronJob{
      expr:     expr,
      nextTime: expr.Next(now),
   }
   //将任务1注册到调度表
   scheduleTable["job2"] = cronJob
   //启动一个调度协程
   go func() {
      var(
         jobName string
         cronJob *CronJob
         now time.Time
      )
      //定期检查调度表
      for {
         now = time.Now()
         for jobName,cronJob = range scheduleTable {
            //判断是否过期
            if cronJob.nextTime.Before(now) || cronJob.nextTime.Equal(now) {
               //启动一个协程,执行这个任务
               go func(jobName string) {
                  fmt.Println("执行:",jobName)
               }(jobName)
            }
            //计算下一次的调度时间
            cronJob.nextTime = cronJob.expr.Next(now)
            fmt.Println(jobName,"下次执行的时间:",cronJob.nextTime)
         }
      }
      //睡眠100毫秒,进入下一次循环
      select {
      case <- time.NewTimer(100*time.Millisecond).C: //将在100毫秒可读,返回
      }
   }()
   time.Sleep(100*time.Second)
}

etcd的使用

  • 与etcd建立连接
package main

import (
   "fmt"
   "github.com/coreos/etcd/clientv3"
   "time"
)
func main()  {
   var (
      config clientv3.Config
      client *clientv3.Client
      err error
   )
   //客户端配置
   config = clientv3.Config{
      Endpoints:            []string{"192.168.56.11:2379"},
      DialTimeout:          5*time.Second,
   }
   //建立连接
   if client,err = clientv3.New(config);err != nil {
      fmt.Println(err)
      return
   }
   client = client
}
  • 插入键值对
package main

import (
   "context"
   "fmt"
   "github.com/coreos/etcd/clientv3"
   "time"
)

func main() {
   var (
      config clientv3.Config
      client *clientv3.Client
      err error
      kv clientv3.KV
      putResp *clientv3.PutResponse
   )
   //建立连接
   config = clientv3.Config{
      Endpoints:            []string{"192.168.56.11:2379"},
      DialTimeout:          5*time.Second,
   }

   if client,err = clientv3.New(config);err!=nil {
      fmt.Println(err)
      return
   }

   //读写etcd的键值对
   kv = clientv3.NewKV(client)
   //kv.Put(ctx context.Context())
   if putResp,err = kv.Put(context.TODO(),"/cron/jobs/job1","hello",clientv3.WithPrefix());err != nil {
      fmt.Println(err)
      return
   }else {
      fmt.Println(putResp.Header.Revision)
      if putResp.PrevKv != nil {
         fmt.Println("PrevValue:",string(putResp.PrevKv.Value))
      }
   }
}
  • 读写etcd键值对
package main

import (
   "context"
   "fmt"
   "github.com/coreos/etcd/clientv3"
   "time"
)

func main() {
   var (
      config  clientv3.Config
      client  *clientv3.Client
      err     error
      kv      clientv3.KV
      getResp *clientv3.GetResponse
   )
   //建立连接
   config = clientv3.Config{
      Endpoints:   []string{"192.168.56.11:2379"},
      DialTimeout: 5 * time.Second,
   }

   //建立客户端
   if client, err = clientv3.New(config); err != nil {
      fmt.Println(err)
      return
   }
   //用于读写etcd键值对
   kv = clientv3.NewKV(client)

   if getResp,err = kv.Get(context.TODO(),"/cron/jobs/job1",/*clientv3.WithCountOnly())*/);err !=nil {
      fmt.Println(err)
      return
   }else {
      fmt.Println(getResp.Kvs,getResp.Count)
   }
}
  • 按目录读取键值对
package main

import (
   "context"
   "fmt"
   "github.com/coreos/etcd/clientv3"
   "time"
)

//按目录获取
func main() {
   var (
      config  clientv3.Config
      client  *clientv3.Client
      err     error
      kv      clientv3.KV
      getResp *clientv3.GetResponse
   )
   //建立连接
   config = clientv3.Config{
      Endpoints:   []string{"192.168.56.11:2379"},
      DialTimeout: 5 * time.Second,
   }

   //建立客户端
   if client, err = clientv3.New(config); err != nil {
      fmt.Println(err)
      return
   }
   //用于读写etcd键值对
   kv = clientv3.NewKV(client)
   //取/cron/jobs/为前缀的所有key
   if getResp,err = kv.Get(context.TODO(),"/cron/jobs",clientv3.WithPrefix());err != nil {
      fmt.Println(err)
      return
   }else {
      //获取所有的kvs
      fmt.Println(getResp.Kvs)
   }
}