一、介绍cli包
我们首先介绍一个用于构建命令行应用程序的go语言包:github.com/urfave/cli
。
它提供了一组功能强大且易于使用的工具,用于定义命令、解析命令行参数、执行命令以及处理应用程序的输入和输出等任务。
下面简单介绍一下这个包的使用
1.1 首先启动一个新的 cli 程序
app := cli.NewApp()
1.2 设置应用程序的名称、版本和用法说明
app.Name = "memo" // 程序的名字
app.Version = "1.0.0" // 程序的版本号
app.Usage = "A simple command line memo application" // 程序简介
1.3 添加程序的命令
部分参数介绍:
Name
:参数名。Aliases
:参数的其他名称。这是一个[]string
切片,里面所有的值都与 Name 字段里设定的等价。同时后面{"a"}
的字母是参数的别名,意味着用户可以使用add
或者a
来调用这个命令。Usage
:这个命令的简单介绍。Action
:指定命令被调用后所执行的函数。
app.Commands = []cli.Command{
{
Name: "add",
Aliases: []string{"a"},
Usage: "Add a new memo item",
Action: addMemo,
},
{
Name: "list",
Aliases: []string{"l"},
Usage: "List all memo items",
Action: listMemo,
},
{
Name: "delete",
Aliases: []string{"d"},
Usage: "Delete a memo item",
Action: delMemo,
},
}
1.4 最后运行应用程序
app.Run(os.Args)
二、实现记事本的功能
我们注意到上面1.3中介绍了每个命令都有对应的执行函数。
那么接下来我们把对应的函数实现一下就可以了
2.1 往记事本中添加内容
- 先获取命令行中输入的内容
- 获取到记事本中原先的内容
- 将新的内容追加到记事本中
func addMemo(c *cli.Context) error {
// 读取命令 输入 内容
text := c.Args().First()
// 读取 记事本 现有内容
items, err := readMemo()
if err != nil {
fmt.Println("读取内容失败")
return err
}
// 实例化结构体
item := MemoItem{
ID: len(items) + 1,
Text: text,
Time: time.Now().Format("2006-01-02 15:04:05"),
}
// 追加内容
items = append(items, item)
// 将所有内容 重新写入 记事本
if err = writeMemo(items); err != nil {
fmt.Println("追加内容后写入记事本出错")
return err
}
return nil
}
2.2 删除某条记录
- 获取命令行中要删除的 id
- 读取记事本中所有内容存入到切片中
- 对切片进行切割再合并,保证切掉要删除的内容
- 因为删除一个元素后 id 会乱,所以对 id 进行重排列
- 在将新的切片存入到记事本中
func delMemo(c *cli.Context) error {
// 获取命令 后 对应的 id值
idd := c.Args().First()
id, err := strconv.Atoi(idd)
if err != nil {
fmt.Println("整数转换失败!")
return err
}
// 读取 记事本 目前所有内容
items, err := readMemo()
if err != nil {
return err
}
// 在原来 的 基础上 进行 切除
items = append(items[:id-1], items[id:]...)
// 删除后,格式化序号
if err != nil {
return err
}
var redoItems []MemoItem
for i, text := range items {
item := MemoItem{
ID: i + 1,
Text: text.Text,
Time: text.Time,
}
redoItems = append(redoItems, item)
}
err = writeMemo(redoItems)
if err != nil {
fmt.Println("格式化重新写入操作失败!")
return err
}
return nil
}
2.3 查看记事本所有内容
- 直接读取记事本的所有内容
- 格式化展示出来
func listMemo(c *cli.Context) error {
// 读取 记事本 现有内容
items, err := readMemo()
if err != nil {
fmt.Println("读取记事本内容失败")
return err
}
// 遍历 所有内容 格式化
for _, item := range items {
fmt.Printf("%d: %s %s\n", item.ID, item.Text, item.Time)
}
return nil
}
func readMemo() ([]MemoItem, error) {
fileData, err := ioutil.ReadFile("data.json")
if err != nil {
/*
如果此时 没有 data.json文件,那就没办法读取内容,会导致报错
所以 返回一个 空集合
让后续写入的时候,进行创建文件
*/
if os.IsNotExist(err) {
return []MemoItem{}, nil
}
return nil, err
}
var items []MemoItem
// 将读取到的内容 填充到 items结构体中
err = json.Unmarshal(fileData, &items)
if err != nil {
return nil, err
}
return items, nil
}
效果展示
项目地址:
gitee: go实现命令行记事本—gitee地址
github:go实现命令行记事本—github地址
附:
ioutil.WriteFile
: 如果在进行写入操作的时候,没有目标文件,会自动创建并且写入。json.Unmarshal
:将json格式的数据,转换为 go中的数据结构(如:结构体等)。json.MarshalIndent
:将go的数据结构 格式化 成json格式的数据。