Go基礎系列:讀取標準輸入(一)

fmt包中提供了3類讀取輸入的函數:web

  • 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家族的函數都返回讀取的記錄數量,並會設置報錯信息,例如讀取的記錄數量不足、超出或者類型轉換失敗等。spa

如下是它們的定義方式:code

$ 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類函數是同樣的。orm

Scan、Scanf和Scanln

Scan家族函數從標準輸入讀取數據時,將以空格爲分隔符分隔標準輸入中的內容,並將分隔後的各個記錄保存到給定的變量中。其中Scanf()能夠指定分隔符。字符串

例如,使用Scanln函數等待用戶輸入數據,或從管道中讀取數據。下面的代碼將等待用戶輸入,且將讀取的內容分別保存到name變量和age變量中:input

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的時候終止讀取,因此在輸入的時候只要按下回車鍵就會結束讀取。string

運行它,將提示輸入姓名:it

請輸入姓名和年齡,空格分隔:
周伯通 69
name: 周伯通
age: 69

同理Scanf()也在遇到換行符或EOF的時候終止讀取行爲。使用Scanf()的時候,須要給定格式化字符串形式:
例如:io

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包也能夠讀取標準輸入。固然,讀取標準輸入只是它的一個功能示例,它的做用是操做緩衝

相關文章
相關標籤/搜索