美文网首页Go入门系列
Go入门系列(六)I/O

Go入门系列(六)I/O

作者: RabbitMask | 来源:发表于2020-03-16 18:32 被阅读0次

目录:
一、终端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语言是不允许声明却不使用的,这属于语法错误,当然,这里也可以不加,本教程刻意而为之只是想做个提醒。
我们查看ScanforScanln方法可以看到,实际上这两个方法是存在返回值的:

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
文件读取结束...
/狡辩

作为入门系列本章选取了较为主流且简单的实现方式,实际使用中可根据个人习惯选择。

相关文章

  • Go入门系列(六)I/O

    目录:一、终端I/O二、文件I/O 一、终端I/O Go语言的终端I/O操作在基础包上有封装了多种,我们以fmt包...

  • Go netpoller

    摘要 这边文章将介绍 Go 如何处理网络 I/O 阻塞I/O 在Go中,所有的I/O都是阻塞的。 Go生态系统是围...

  • Go语言学习四:I/O

    Go 语言I/O 涉及两大部分 :I/O ,File 一 I/O /** bufio包实现了有缓冲的I/O。它包装...

  • 2017年为什么要努力?这是我见过最好的回答

    I Believe I Can Fly I used to think that I could not go o...

  • 问问答答

    When do you go to school? I go to school, at, seven o'clo...

  • Python入门系列(七)——I/O

    目录:一、界面I/O二、文件I/O 一、界面I/O 我也不知道这么称呼是否贴切,python首先要提到的就是用户交...

  • One Funny Day

    On Sunday.I go to the supermarket with mother.I buy lot o...

  • 作业

    今儿作业多(๑•́o•̀๑) ↯↯,but I am a Straight A studentm. I am go...

  • go build

    控制台编译,少不了使用:go build,用法: usage: go build [-o output] [-i]...

  • Go WebAssembly 入门(二)

    系列文章 Go WebAssembly 入门(一) Getting Started 编写main.go 将main...

网友评论

    本文标题:Go入门系列(六)I/O

    本文链接:https://www.haomeiwen.com/subject/xbjcehtx.html