服务计算作业3----------使用 golang 开发 selpg
文章目录
实验目的
使用 golang 开发 开发 Linux 命令行实用程序 中的 selpg
提示:
- 请按文档使用 selpg 章节要求测试你的程序
- 请使用 pflag 替代 goflag 以满足 Unix 命令行规范, 参考:Golang之使用Flag和Pflag
- golang 文件读写、读环境变量,请自己查 os 包
- “-dXXX” 实现,请自己查 os/exec 库,例如案例 Command,管理子进程的标准输入和输出通常使用 io.Pipe,具体案例见 Pipe
实验预备
1. 学习pflag包
Golang官方的命令行参数解析库flag,已经用的比较少。而是Google的一位Golang大牛Steve Francia自己写的命令行参数解析库pflag更加优秀,从而得到广泛使用。
根据pflag作者的说法,pflag是golang的原生falg包的直接替代品,如果您在之前使用flag包的情况下导入pflag,则所有代码可以继续运行而不用进行任何更改.
安装和导入pflag
使用 go get
命令就可以安装pflag包
go get github.com/spf13/pflag
使用go test
测试是否安装成功
go test github.com/spf13/pflag
在代码内导入pfalg
import "github.com/spf13/pflag"
了解使用pflag
flag和pflag都是源自于Google,工作原理甚至代码实现基本上都是一样的。 flag虽然是Golang官方的命令行参数解析库,但是pflag却得到更加广泛的应用。 因为pflag相对flag有如下优势:
- 支持更加精细的参数类型:例如,flag只支持uint和uint64,而pflag额外支持uint8、uint16、int32。
- 支持更多参数类型:ip、ip mask、ip net、count、以及所有类型的slice类型,例如string slice、int slice、ip slice等。
- 兼容标准flag库的Flag和FlagSet。
- 原生支持更丰富flag功能:shorthand、deprecated、hidden等高级功能。
所以pflag的使用与flag基本是相同的:
1. 定义flags
- 将flag绑定到一个变量* 将flag绑定到一个变量
import "flag" var flagvar int func init() { flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") }
- 相比起来,pflag可以在绑定时直接绑定shorthand
import "github.com/spf13/pflag" // func (f *FlagSet) IntVarP(p *int, name, shorthand string, value int, usage string) // IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash. var flagvar int pflag.IntVarP(&flagvar, "flagname", "f", 1234, "help message for flagname")
- 还有其他定义方式
- pfalg
// func IntP(name, shorthand string, value int, usage string) *int // IntP is like Int, but accepts a shorthand letter that can be used after a single dash. var ip= pflag.IntP("flagname", "f", 1234, "help message for flagname")
- flag
import "flag" // 返回的是 指针 var ip = flag.Int("flagname", 1234, "help message for flagname")
- pfalg
2. 解析Flag
定义命令行参数之后,和使用命令行参数之前,必须调用pflag.Parse()来解析命令行参数。pflag.Parse()使CommandLine解析除命令行除第一个参数外的所有参数.
// Parse parses the command-line flags from os.Args[1:]. Must be called
// after all flags are defined and before flags are accessed by the program.
func Parse() {
// Ignore errors; CommandLine is set for ExitOnError.
CommandLine.Parse(os.Args[1:])
}
2. 学习文件读写
因为此次作业要求要进行文件的按行和按页读取,根据Google的结果来看最好的方法应该是使用package bufio所以接下来我们要学习使用package bufio
bufio包实现了有缓冲的I/O。它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文本I/O的帮助函数的对象
1. 导入bufio包
import "bufio"
2.按行读取
通过阅读文档我发现了一个ReadLine的函数,似乎可以直接使用,但是文档表示不推荐
既然如此我们采用文档推荐的ReadString(’\n’)
具体方法如下:
package main
import (
"os"
"bufio"
)
func main(){
fin, err = os.Open(fileName) //打开文件,默认为只读
if err != nil { //打开出错
fmt.Fprintf(os.Stdout, "can not open the file\"%s\"\n", fileName)
fmt.Println(err)
os.Exit(1)
}
defer fin.Close() //结束后关闭文件
//func NewReader(rd io.Reader) *Reader
//NewReader创建一个具有默认大小缓冲、从r读取的*Reader
//Reader实现了给一个io.Reader接口对象附加缓冲
reader := bufio.NewReader(fin)
line , lerr := lreader.ReadString('\n')
//如此line就为读到的一行数据
}
3. 按页读取
同上理,按页可以使用ReadString(’\f’)但是这会让读到的数据保留'\f'
字符,而'\f'
字符
会在标准输出到命令行时,可能会产生如同水平制表符的效果.