服务计算 用Golang写出简易的selpg
文章目录
1.项目概述:
CLI(Command Line Interface)实用程序是Linux下应用开发的基础。正确的编写命令行程序让应用与操作系统融为一体,通过shell或script使得应用获得最大的灵活性与开发效率。Linux提供了cat、ls、copy等命令与操作系统交互;go语言提供一组实用程序完成从编码、编译、库管理、产品发布全过程支持;容器服务如docker、k8s提供了大量实用程序支撑云服务的开发、部署、监控、访问等管理任务;git、npm等都是大家比较熟悉的工具。尽管操作系统与应用系统服务可视化、图形化,但在开发领域,CLI在编程、调试、运维、管理中提供了图形化程序不可替代的灵活性与效率。
而我们本次的任务是使用 golang 开发一个简易的 selpg
。
那么,首先我们需要明白的是,selpg
到底是什么?在IBM Developer
上面有很详细的项目说明,简单点来说,这是一个叫做Select PaGes
的实用程序,用户可以指定的抽出输入文本的一定范围的页。例如,输入是一个有100多页的文件,而我们只需要其实的31-65页的内容,这个时候,selpg
就显得很有价值。
如果直接让我们写出这个程序的话,我觉得以我的菜鸡能力是肯定写不出来的,所幸IBM Developer
中的开发人员给出了项目的c语言代码,我们实质上需要做的工作就是将c语言项目转化为Golang项目。分析完c语言代码,我觉得代码主要可以分成以下几个部分来写:
2.过程分析:
A. 命令行参数分析
-s [Number]
:就是我们制定开始的页码,在我们的项目中,0是开始项。-e [Number]
:指定的结束项。-l [Number]
:一页有多少行,默认的为72。-f
:程序自动忽略-l
,在整个文档中寻找换行符\f
,并且将其作为分页的标志。-d [dest]
:指定目标打印。[In_file]
:输入文件名。在所有-
类型参数后指定,selpg
会自动查找,如果查找不到,就读取stdin中的内容作为输入。
B. 程序分析
一、引入相关包
在程序设计中,我们往往利用flag包
来进行命令行参数的解析,事实上,pflag
包比flag
包的应用范围更广一点,因此这次我们直接调用pflag
包 。
在这之前,你需要在terminal中输入以下指令,安装好这个包:
go get github.com/spf13/pflag //安装
go test github.com/spf13/pflag //测试是否安装好
为了更好的的完成程序,我们也引用了其他的包,具体的如下图:
import(
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
flag "github.com/spf13/pflag"
)
我们直接利用flag "github.com/spf13/pflag"
语句,就可以直接使用flag,但是也可以调用pflag
的功能。
二、创建结构体
我们创建以下几个参数,命名啥的基本都是参照原来的c程序:
- start_page:起始页
- end_page:结束页
- in_filename: 输入的文件名
- destination:
-d
后面跟着的目的地 - page_len:每页的行数
- page_type:判断页的类型
具体的代码如下:
type selpg_args struct {
start_page int
end_page int
in_filename string
destination string
page_len int
page_type bool
}
三、初始化
这里面我们主要要用到flag.XxxVar()
,用来将flag绑定到一个变量上面。例如:
var flagvar int
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
我们利用这个函数来对我们的相关变量金星初始化,pflag则是 XxxVarP
, 话不多说:
flag.Usage = Usage
flag.IntVarP(&args.start_page, "start_page", "s", -1, "sepcify start page")
flag.IntVarP(&args.end_page, "end_page", "e", -1, "end page")
flag.StringVarP(&args.destination, "destination", "d", "", "print destination")
flag.IntVarP(&args.page_len, "pageLength", "l", 72, "lines per page")
flag.BoolVarP(&args.page_type, "pageType", "f", false, "page type")
flag.Parse() //调用flag.Parse()进行解析
四、 process_args 函数:
这个函数主要是用于处理输入时候的各种错误,比如起始页码是负数,终止页码小于起始页码等情况,增加程序的健壮性,因为事实上这个部分就是对照着给定的C语言代码改的……所以也没有什么好说的,我们只选取其中的部分作为展示:
if len(os.Args) <= 3 {
fmt.Fprintf(os.Stderr, "\n Error: \n %s: arguments are not enough\n\n", progname)
flag.Usage()
os.Exit(1)
}
if args.start_page < 0 && args.end_page < 0 {
fmt.Fprintf(os.Stderr, "\n Error: \n %s: arguments are not enough\n\n", progname)
flag.Usage()
os.Exit(1)
}
……
……
if args.start_page > args.end_page || args.start_page < 0 || args.end_page < 0 {
fmt.Fprintf(os.Stderr, "\n Error: \n %s: Invalid arguments\n\n", progname)
flag.Usage()
os.Exit(1)
}
五、process_input 函数:
这个部分主要用来对文件的内容进行处理,然后根据后缀参数的类型完成操作,这个部分参考了很多师兄们以前的代码2333……下面放出来一部分:
var cmd *exec.Cmd
var cmdIn io.WriteCloser
var cmdOut io.ReadCloser
if args.destination != "" {
cmd = exec.Command("bash", "-c", args.destination)
cmdIn, _ = cmd.StdinPipe()
cmdOut, _ = cmd.StdoutPipe()
cmd.Start()
}
主函数之类的就不说了,按照c语言的代码改过来就可以了……
3.运行结果:
比较惨的是国庆回来,发现安装的几个虚拟机,无论是ubuntu
,还是centOS
,全部打不开了……因为时间比较紧,配置环境也比较麻烦,我们这次就直接是放置在TA师兄开发的 GoOnline
运行的,有兴趣的同学们看到这篇博客亦可以自己去尝试一哈师兄们开发的这个在线编程平台,网址如下:
GoOnline
我们用data
这个文件来作为我们的In_file
,用来存储我们的实验数据,output
这个文件来存储输出数据,下面我们开始尝试一些相关的指令,因为篇幅原因,我们只尝试部分:
先在terminal输入:
go build test.go
-
./test -s0 -e0 -l 10 data
我们设定一页有10行,输出第一页
-
./test -s1 -e2 -l 5 data
一页5行,第二页到第三页
-
./test -s1 -e2 -l 5 data >output
将其输出到output
文件
-
如果起始页大于结束页,就会直接报错:
还有很多在这里就不一一列举了,具体的可以直接自己尝试一哈。
我的Github地址为:
戳这里
4.参考博客及网址:
- https://pmlpml.github.io/ServiceComputingOnCloud/ex-cli-basic
- https://o-my-chenjian.com/2017/09/20/Using-Flag-And-Pflag-With-Golang/
- https://www.ibm.com/developerworks/cn/linux/shell/clutil/index.html
- https://blog.csdn.net/wyxwyx469410930/article/details/82952728
- https://studygolang.com/articles/5608nd-Pflag-With-Golang/
- https://www.ibm.com/developerworks/cn/linux/shell/clutil/index.html
- https://blog.csdn.net/wyxwyx469410930/article/details/82952728
- https://studygolang.com/articles/5608
- https://blog.csdn.net/myMatthew/article/details/78448562