Go入门系列(六)I/O
2020-03-16 本文已影响0人
RabbitMask
目录:
一、终端I/O
二、文件I/O
一、终端I/O
Go语言的终端I/O操作在基础包上有封装了多种,我们以fmt包为例:
如果为单次输入,可使用Scanln
,如一次输入多个变量,可使用Scanf
。
func main() {
var name string
var age int
fmt.Print("请输入姓名:")
_, _ = fmt.Scanln(&name)
fmt.Print("请输入年龄:")
_, _ = fmt.Scanln(&age)
fmt.Printf("您的姓名为:%s,您的年龄为:%d",name,age)
}
#输出
请输入姓名:rabbit
请输入年龄:18
您的姓名为:rabbit,您的年龄为:18
大家可能注意到与网上常见的教程不一样,这里使用了两个忽略符:_, _
,可以简单理解为赋值但以后不再使用,因为Go语言是不允许声明却不使用的,这属于语法错误,当然,这里也可以不加,本教程刻意而为之只是想做个提醒。
我们查看Scanf
orScanln
方法可以看到,实际上这两个方法是存在返回值的:
func Scanln(a ...interface{}) (n int, err error) {
return Fscanln(os.Stdin, a...)
}
我们接下来以Scanf
为例启用返回值:
func main() {
var name string
var age int
fmt.Print("请输入姓名和年龄:")
_, err := fmt.Scanf("%s %d",&name,&age)
if err != nil{
println(err.Error())
}else {
fmt.Printf("您的姓名为:%s,您的年龄为:%d",name,age)
}
}
#输出
请输入姓名和年龄:rabbit 18
您的姓名为:rabbit,您的年龄为:18
如错误输入,打印报错:
请输入姓名和年龄:rabbit rabbit
expected integer
顺便来探讨下,如果跟其它教材一样不启用错误处理会怎么样呢?
func main() {
var name string
var age int·
fmt.Print("请输入姓名和年龄:")
fmt.Scanf("%s %d",&name,&age)
fmt.Printf("您的姓名为:%s,您的年龄为:%d",name,age)
}
#输出
请输入姓名和年龄:rabbit rabbit
您的姓名为:rabbit,您的年龄为:0
关于输出前面基本涉及了,简单总结一下fmt包中常用的三个方法:
Println :可以打印出字符串,和变量
Printf : 只可以打印出格式化的字符串,可以输出字符串类型的变量,不可以输出整形变量和整形
Print:效果同Println,但没有自动换行,需手动增加\n
此外fmt包外还有一个打印方法:print,然而在golang中,其属于输出到标准错误流中并打印,官方不建议写程序时候用它,可以在debug时候用。
二、文件I/O
- 文件创建
func main(){
f, err := os.Create("user.txt")
if err != nil {
fmt.Println("Create err:", err)
}
defer f.Close()
fmt.Println("create successful")
}
#输出
create successful
查看Create方法我们可以对返回值根据清晰,其中f为指针类型。
func Create(name string) (*File, error) {
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
- 文件写入
Go语言的文件写入多个包都具备该功能,os包、io包、ioutil包、bufio 包。
本章以os包为例,文件写入用到OpenFile()方法。
func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
参1:name,表示打开文件的路径。可使用相对路径 或 绝对路径
参2:flag,表示读写模式,常见的模式有:
O_RDONLY(只读模式), O_WRONLY(只写模式), O_RDWR(可读可写模式), O_APPEND(追加模式)。| O_CREATE (当有此参数,必须指定 参数3)
参3:perm,表权限取值范围(0-7),表示如下:
0:没有任何权限
1:执行权限(如果是可执行文件,是可以运行的)
2:写权限
3: 写权限与执行权限
4:读权限
5: 读权限与执行权限
6: 读权限与写权限
7: 读权限,写权限,执行权限
借助OpenFile()方法,我们尝试进行文本的创建和写入:
func main() {
filePath := "user.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
checkErr(err)
defer file.Close()
str := "hello world\n"
for i := 0; i < 3; i++ {
file.WriteString(str)
}
}
func checkErr(err error) {
if err != nil {
fmt.Println(err.Error())
return
}
}
#user.txt
hello world
hello world
hello world
此外,我们可以借助bufio包实现缓冲写入,即借助带缓存的*writer,所有操作先写入缓存,在执行Flush()方法是才写入文本。
func main() {
filePath := "user.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
checkErr(err)
defer file.Close()
str := "hello world\n"
writer := bufio.NewWriter(file)
for i := 0; i < 3; i++ {
writer.WriteString(str)
}
writer.Flush()
}
func checkErr(err error) {
if err != nil {
fmt.Println(err.Error())
return
}
}
#user.txt
hello world
hello world
hello world
通过适度的缓冲区大小,我们可以提高Go在操作较大数据量时候的程序性能。
- 文件读取
方式依然很多,因人而异,如不使用缓冲区,可借助io包完成:
func main() {
file, err := ioutil.ReadFile(`user.txt`)
if err != nil {
panic(err)
}
fmt.Println(string(file))
}
#输出
hello world
hello world
hello world
使用缓冲区可依然借助os包和bufio实现:
func main() {
file, err := os.Open("user.txt")
checkErr(err)
defer file.Close()
reader := bufio.NewReader(file)
for {
str, err := reader.ReadString('\n')
if err == io.EOF {
break
}
fmt.Print(str)
}
fmt.Println("文件读取结束...")
}
func checkErr(err error) {
if err != nil {
fmt.Println(err.Error())
return
}
}
#输出
hello world
hello world
hello world
文件读取结束...
/狡辩
作为入门系列本章选取了较为主流且简单的实现方式,实际使用中可根据个人习惯选择。