当前位置: 移动技术网 > IT编程>脚本编程>Go语言 > Go基础系列:读取标准输入

Go基础系列:读取标准输入

2018年11月12日  | 移动技术网IT编程  | 我要评论

fmt包中提供了3类读取输入的函数:

  • scan家族:从标准输入os.stdin中读取数据,包括scan()、scanf()、scanln()
  • sscan家族:从字符串中读取数据,包括sscan()、sscanf()、sscanln()
  • fscan家族:从io.reader中读取数据,包括fscan()、fscanf()、fscanln()

其中:

  • scanln、sscanln、fscanln在遇到换行符的时候停止
  • scan、sscan、fscan将换行符当作空格处理
  • scanf、sscanf、fscanf根据给定的format格式读取,就像printf一样

这3家族的函数都返回读取的记录数量,并会设置报错信息,例如读取的记录数量不足、超出或者类型转换失败等。

以下是它们的定义方式:

$ go doc fmt | grep -ei "func [fs]*scan"
func fscan(r io.reader, a ...interface{}) (n int, err error)
func fscanf(r io.reader, format string, a ...interface{}) (n int, err error)
func fscanln(r io.reader, a ...interface{}) (n int, err error)
func scan(a ...interface{}) (n int, err error)
func scanf(format string, a ...interface{}) (n int, err error)
func scanln(a ...interface{}) (n int, err error)
func sscan(str string, a ...interface{}) (n int, err error)
func sscanf(str string, format string, a ...interface{}) (n int, err error)
func sscanln(str string, a ...interface{}) (n int, err error)

因为还没介绍io.reader,所以fscan家族的函数暂且略过,但用法和另外两家族的scan类函数是一样的。

scan、scanf和scanln

scan家族函数从标准输入读取数据时,将以空格为分隔符分隔标准输入中的内容,并将分隔后的各个记录保存到给定的变量中。其中scanf()可以指定分隔符。

例如,使用scanln函数等待用户输入数据,或从管道中读取数据。下面的代码将等待用户输入,且将读取的内容分别保存到name变量和age变量中:

package main

import (
    "fmt"
)

func main() {
    var (
        name string
        age  int
    )
    fmt.print("输入姓名和年龄,使用空格分隔:")
    fmt.scanln(&name, &age)
    fmt.printf("name: %s\nage: %d\n", name, age)
}

因为scanln()遇到换行符或eof的时候终止读取,所以在输入的时候只要按下回车键就会结束读取。

运行它,将提示输入姓名:

请输入姓名和年龄,空格分隔:
周伯通 69
name: 周伯通
age: 69

同理scanf()也在遇到换行符或eof的时候终止读取行为。使用scanf()的时候,需要给定格式化字符串形式:
例如:

fmt.scanf("%s %d",&name,&age)

输入时,第一个字段会转换成字符串格式保存到name变量中,第二个记录会转换成整数保存到age中,如果转换失败,将不会进行保存。例如输入malongshuai aaa,由于aaa无法转换成int,所以age变量的值仍然为初始化的数值0。

scanf可指定分隔符,其中上面的是%s %d中间的空格就是分隔符。例如下面指定:作为分隔符:

fmt.scanf("%s : %d",&name,&age)

在输入时,必须按照以下格式进行输入:首先至少一个空格,然后一个冒号,再至少一个空格:

周伯通 : 23    // 或者连续多个空格  "周伯通     :   23"
name: 周伯通
age: 23

如果使用的是fmt.scan(),则输入数据时可以换行输入,scan()会将换行符作为空格进行处理,直到读取到了2个记录之后自动终止读取操作:

fmt.scan(&name, &age)

请输入姓名和年龄,空格分隔:周伯通
87
name: 周伯通
age: 87

一般来说,只使用scanf类函数比较好。

返回值

这些函数都有返回值:读取的记录数量和err信息。

以scanln()为例:

func main() {
    var (
        name string
        age  int
    )
    fmt.print("输入姓名和年龄,使用空格分隔:")
    n, err := fmt.scanln(&name, &age)

    fmt.printf("name: %s\nage: %d\n", name, age)

    fmt.println("records count:",n)
    fmt.println("err or not:",err)
}

输入:

malongshuai 23     // n = 2, err = nil
malongshuai        // n = 1, err != nil
malongshuai long   // n = 2, err != nil
malongshuai 23 23  // n = 2, err != nil

sscan、sscanf和scanln

sscan家族的函数用于从给定字符串中读取数据,用法和scan家族类似。

func sscan(str string, a ...interface{}) (n int, err error)
func sscanln(str string, a ...interface{}) (n int, err error)
func sscanf(str string, format string, a ...interface{}) (n int, err error)

例如:

package main

import (
    "fmt"
)

func main() {
    var (
        name string
        age  int
    )
    input := "malongshuai 23"

    fmt.sscan(input, &name, &age)
    fmt.printf("name: %s\nage: %d\n", name, age)
}

使用sscanf()可以指定分隔符:

input := "malongshuai : 23"

fmt.sscanf(input, "%s : %d", &name, &age)

使用bufio中读取标准输入

除了fmt包的scan类函数,bufio包也可以读取标准输入。当然,读取标准输入只是它的一个功能示例,它的作用是操作缓冲io。

package main

import (
    "bufio"
    "fmt"
    "os"
)

var inputreader *bufio.reader
var input string
var err error

func main() {
    inputreader = bufio.newreader(os.stdin)
    fmt.println("输入姓名:")
    input, err = inputreader.readstring('\n')
    if err == nil {
        fmt.printf("the input was: %s\n", input)
    }
}

其中newreader()创建一个bufio.reader实例,表示创建一个从给定文件中读取数据的读取器对象。然后调用读取器对象(reader实例)的readstring()方法,这个方法以\n作为分隔符,它的分隔符必须只能是单字符,且必须使用单引号包围,因为它会作为byte读取。readstring()读取来自os.stdin的内容后将其保存到input变量中,同时返回是否出错的信息。readstring()只有一种情况会返回err:没有遇到分隔符。

readstring会将读取的内容包括分隔符都一起放进缓冲中,如果读取文件时读到了结尾,则会将整个文件内容放进缓冲,并将文件终止标识符io.eof放进设置为err。

通常无需单独定义这些变量,下面是更常见的用法。

inputreader := bufio.newreader(os.stdin)
input, err := inputreader.readstring('\n')

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网