基本知识:

cobra

cobra是一个开发命令行的golang库,很多流行的命令行都基于这个库开发,比如kubectl, etcdctl, docker, hugo等。

cobra命令函数RunE的执行前后可以设置2组Hook,执行顺序如下:

  • PersistentPreRunE: 无论函数执不执行,该函数都会运行
  • PreRunE: 在函数执行前执行
  • RunE: 执行函数
  • PostRunE: 在函数执行后执行
  • PersistentPostRunE: 无论函数执不执行,该函数都会执行

最后字母E表示,每个函数都会有error返回。

RPC

RPC(Remote Procedure Call)远程过程调用,是一个通信协议,从一台机器上通过参数传递的方式调用另一台机器上的一个函数或方法并得到响应结果,形式上像调用本地函数一样。

在golang中,官方提供了rpc, jsonrpc包。rpc包支持TCP,HTTP不同的协议。rpc使用gob对数据进行序列化与反序列化。jsonrpc基于TCP协议,将数据序列化为json格式进行传输。

使用场景:

命令行运行一个主程序负责Task任务的执行,通过执行命令创建Task,查看和启停Task。

所以根命令行包括两个命令,daemon,task。在task命令下又包含多个子命令,这里task是一个资源,就像Restful的客户端,create, list, delete, start, stop。

代码开发

main入口

newCommandsBuilder构造一个commandsBuilder对象

addAll将各个命令加入到commandsBuilder.commands中

在build中,newAilabelCmd构造一个rootCommand,在这个rootCommand中,有一个PersistentFlags持久化标签,这是一个全局参数,参数名为port,他对这个rootCommand以及他的子命令都有效,命令行输入命令时都可以加上这个参数来使用。

在build中,addCommands这个方法将commandsBuilder.commands中的命令都Add到rootCommand中。

daemon命令

grpcserver.NewRPCServer启动一个rpcServer

在NewRPCServer中,通过go官方的rpc构造一个rpc server,注册名为"Tasks"的服务,通过httpServer对外提供服务。

Tasks服务的CreateTask,ListTasks方法,这里可以注意到,rpc要求服务的每个方法都是有两个输入参数,用于请求和响应,还需要有一个返回参数,用于方法执行结果。

taskStore.CreateTask调用boltdb的put方法写入boltdb数据

taskStore.ListTasks调用boltdb的ViewForEach方法取出boltdb数据

Task命令

Task命令添加了两个子命令:CreateTaskCmd, ListTasksCmd

createTaskCmd命令

createTaskCmd里执行命令函数cc.createTask前,有一个勾子函数,调用NewClient创建一个rpc client,createTask中c.client.Call调用rpc的服务,"Tasks.CreateTask"指定服务名和方法名,输入参数,返回参数。

listTaskCmd命令

call调用"Tasks.ListTasks"服务的方法,将结果打印到终端。

执行命令