CLI 命令行实用程序开发实战

来源:互联网 发布:铁三手表 知乎 编辑:程序博客网 时间:2024/05/22 11:48

CLI 命令行实用程序开发实战 - Agenda


1、概述

  命令行实用程序并不是都象 cat、more、grep 是简单命令。go 项目管理程序,类似 java 项目管理 maven、Nodejs 项目管理程序 npm、git 命令行客户端、 docker 与 kubernetes 容器管理工具等等都是采用了较复杂的命令行。即一个实用程序同时支持多个子命令,每个子命令有各自独立的参数,命令之间可能存在共享的代码或逻辑,同时随着产品的发展,这些命令可能发生功能变化、添加新命令等。因此,符合 OCP 原则 的设计是至关重要的编程需求。

任务目标

  1. 熟悉 go 命令行工具管理项目
  2. 综合使用 go 的函数、数据结构与接口,编写一个简单命令行应用 agenda
  3. 使用面向对象的思想设计程序,使得程序具有良好的结构命令,并能方便修改、扩展新的命令,不会影响其他命令的代码
  4. 项目部署在 Github 上,合适多人协作,特别是代码归并
  5. 支持日志(原则上不使用debug调试程序)

2、准备

2.1 Golang 知识整理

这里推荐 time-track 的个人博客,它的学习轨迹与课程要求基本一致。以下是他语言学习的笔记,可用于语言快速浏览与参考:

  • 《Go程序设计语言》要点总结——程序结构
  • 《Go程序设计语言》要点总结——数据类型
  • 《Go程序设计语言》要点总结——函数
  • 《Go程序设计语言》要点总结——方法
  • 《Go程序设计语言》要点总结——接口

以上仅代表作者观点,部分内容是不准确的,请用批判的态度看待网上博客。 切记:

  • GO 不是面向对象(OOP) 的。 所谓方法只是一种语法糖,它是特定类型上定义的操作(operation)
  • 指针是没有 nil 的,这可以避免一些尴尬。 p.X 与 v.x (p 指针, v 值) 在语义上是无区别的,但实现上是有区别的 p.x 是实现 c 语言 p->x 的语法糖
  • zero 值好重要

2.2 JSON 序列化与反序列化

参考:JSON and Go
json 包是内置支持的,文档位置:https://go-zh.org/pkg/encoding/json/

2.3 复杂命令行的处理

不要轻易“发明轮子”。为了实现 POSIX/GNU-风格参数处理,--flags,包括命令完成等支持,程序员们开发了无数第三方包,这些包可以在 godoc 找到。

  • pflag 包: https://godoc.org/github.com/spf13/pflag
  • cobra 包: https://godoc.org/github.com/spf13/cobra
  • goptions 包: https://godoc.org/github.com/voxelbrain/goptions
  • ...
  • docker command 包:https://godoc.org/github.com/docker/cli/cli/command

go dead project 非常有用

这里我们选择 cobar 这个工具。

tip: 安装 cobra

  • 使用命令 go get -v github.com/spf13/cobra/cobra 下载过程中,会出提示如下错误
Fetching https://golang.org/x/sys/unix?go-get=1https fetch failed: Get https://golang.org/x/sys/unix?go-get=1: dial tcp 216.239.37.1:443: i/o timeout

这是熟悉的错误,请在 $GOPATH/src/golang.org/x 目录下用 git clone 下载 sys 和 text 项目,然后使用 go install github.com/spf13/cobra/cobra, 安装后在 $GOBIN 下出现了 cobra 可执行程序。

Cobra 的简单使用

创建一个处理命令 agenda register -uTestUser 或 agenda register --user=TestUser 的小程序。

简要步骤如下:

cobra initcobra add register

需要的文件就产生了。 你需要阅读 main.go 的 main() ; root.go 的 Execute(); 最后修改 register.goinit() 添加:

registerCmd.Flags().StringP("user", "u", "Anonymous", "Help message for username")

Run 匿名回调函数中添加:

username, _ := cmd.Flags().GetString("user")fmt.Println("register called by " + username)

测试命令:

$ go run main.go register --user=TestUserregister called by TestUser

参考文档:

  • 官方文档 推荐
  • Cobra简介 不推荐

3、agenda 开发项目

3.1 需求描述

  • 业务需求:见后面附件
  • 功能需求: 设计一组命令完成 agenda 的管理,例如:
    • agenda help :列出命令说明
    • agenda register -uUserName --password pass -email=a@xxx.com :注册用户
    • agenda help register :列出 register 命令的描述
    • agenda cm ... : 创建一个会议
    • 原则上一个命令对应一个业务功能
  • 持久化要求:
    • 使用 json 存储 User 和 Meeting 实体
    • 当前用户信息存储在 curUser.txt 中
  • 开发需求
    • 团队:2-3人,一人作为 master 创建程序框架,其他人 fork 该项目,所有人同时开发。团队 不能少于 2 人
    • 时间:两周完成
  • 项目目录
    • cmd :存放命令实现代码
    • entity :存放 User 和 Meeting 对象读写与处理逻辑
    • 其他目录 : 自由添加
  • 日志服务
    • 使用 log 包记录命令执行情况

Agenda 业务需求

用户注册

  1. 注册新用户时,用户需设置一个唯一的用户名和一个密码。另外,还需登记邮箱及电话信息。
  2. 如果注册时提供的用户名已由其他用户使用,应反馈一个适当的出错信息;成功注册后,亦应反馈一个成功注册的信息。

用户登录

  1. 用户使用用户名和密码登录 Agenda 系统。
  2. 用户名和密码同时正确则登录成功并反馈一个成功登录的信息。否则,登录失败并反馈一个失败登录的信息。

用户登出

  1. 已登录的用户登出系统后,只能使用用户注册和用户登录功能。

用户查询

  1. 已登录的用户可以查看已注册的所有用户的用户名、邮箱及电话信息。

用户删除

  1. 已登录的用户可以删除本用户账户(即销号)。
  2. 操作成功,需反馈一个成功注销的信息;否则,反馈一个失败注销的信息。
  3. 删除成功则退出系统登录状态。删除后,该用户账户不再存在。
  4. 用户账户删除以后:
    • 以该用户为 发起者 的会议将被删除
    • 以该用户为 参与者 的会议将从 参与者 列表中移除该用户。若因此造成会议 参与者 人数为0,则会议也将被删除。

创建会议

  1. 已登录的用户可以添加一个新会议到其议程安排中。会议可以在多个已注册
    用户间举行,不允许包含未注册用户。添加会议时提供的信息应包括:
    • 会议主题(title)(在会议列表中具有唯一性)
    • 会议参与者(participator)
    • 会议起始时间(start time)
    • 会议结束时间(end time)
  2. 注意,任何用户都无法分身参加多个会议。如果用户已有的会议安排(作为发起者或参与者)与将要创建的会议在时间上重叠 (允许仅有端点重叠的情况),则无法创建该会议。
  3. 用户应获得适当的反馈信息,以便得知是成功地创建了新会议,还是在创建过程中出现了某些错误。

增删会议参与者

  1. 已登录的用户可以向 自己发起的某一会议增加/删除 参与者 。
  2. 增加参与者时需要做 时间重叠 判断(允许仅有端点重叠的情况)。
  3. 删除会议参与者后,若因此造成会议 参与者 人数为0,则会议也将被删除。

查询会议

  1. 已登录的用户可以查询自己的议程在某一时间段(time interval)内的所有会议安排。
  2. 用户给出所关注时间段的起始时间和终止时间,返回该用户议程中在指定时间范围内找到的所有会议安排的列表。
  3. 在列表中给出每一会议的起始时间、终止时间、主题、以及发起者和参与者。
  4. 注意,查询会议的结果应包括用户作为 发起者或参与者 的会议。

取消会议

  1. 已登录的用户可以取消 自己发起 的某一会议安排。
  2. 取消会议时,需提供唯一标识:会议主题(title)。

退出会议

  1. 已登录的用户可以退出 自己参与 的某一会议安排。
  2. 退出会议时,需提供一个唯一标识:会议主题(title)。若因此造成会议 参与者 人数为0,则会议也将被删除。

清空会议

  1. 已登录的用户可以清空 自己发起 的所有会议安排。

4、代码实现

agenda代码实现
我们在实现时考虑的注意点:
(1)、时间格式输入是必须为2017-12-12/12:00,起始时间必须小于结束时间
(2)、必须登陆之后才具备查询会议、创建会议、查询用户等等命令,登陆之后不具备注册register功能。
(3)、其他注意点在上面业务需求中,均已实现。

5、运行截图





注册:密码长度要大于等于6,邮箱格式要正确,手机号码长度必须是11位数字。


登录:由下图,必须登录之后才具备查询会议,用户以及创建会议这些功能。


创建会议避免因为参加者太多,导致命令行太长,所以参加者在输入命令行之后再输入



查询会议:查询某有一段时间内的会议


查询用户:


Meeting.txt


User.txt


log

相关测试还有很多,大家可以运行测试,如有错误或不合理的地方还请您在评论区指出,先表示感谢!