2013-10-24 50 views
1

我想寫一個函數,可以從鍵盤讀取輸入或從一個管道輸入文件一次讀取一行。我已經有一個函數,它類似於鍵盤輸入prompt()在本次測試代碼:去 - 鍵盤或管道文件輸入

package main 

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

func print(format string, a ...interface{}) { 
    fmt.Printf(format+"\n", a...) 
} 

func prompt(format string) string { 
    fmt.Print(format) 
    in := bufio.NewScanner(os.Stdin) 
    in.Scan() 
    return in.Text() 
} 

func greet() { 
    name := prompt("enter name: ") 
    print(`Hello %s!`, name) 
} 

func humor() { 
    color := prompt("enter favorite color: ") 
    print(`I like %s too!`, color) 
} 

func main() { 
    greet() 
    humor() 
} 

這裏,greet()humor()都使用prompt()獲得輸入,如果我運行程序和類型的答覆中將按預期工作。但是,如果我有一個文件a.txt

bobby bill 
soft, blue-ish turquoise 

,然後運行:.\test< a.txt,該程序將輸出:的

enter name: Hello bobby bill! 
enter favorite color: I like too! 

代替:

enter name: Hello bobby bill! 
enter favorite color: I like soft, blue-ish turquoise too! 

據我瞭解,這是因爲在greet()中製作的bufio.Scanner讀取了全部a.txt。通過將bufio.Scanner設置爲全局變量,我可以很容易地解決這個問題,並且每次都使用prompt()而不是創建一個新的bufio.Scanner,但我想知道是否有更好的方法來做到這一點,而不必訴諸於全局變量。

回答

1

您的分析是正確的,問題是bufio.Scanner緩衝的不僅僅是一行文本,所以當您丟棄它時會丟失該輸入。如果您要使用緩衝輸入,則應確保所有內容都使用相同的緩衝區來避免此類問題。

使用全局變量是一種解決方案。另一種方法是創建一個類型來保存bufio.Scanner並將一些函數轉換爲方法。

1

我想說,因爲os.Stdin是一個全局變量,擁有它的全局緩衝版本將是完全合適的。

注意,Go沒有真正的全局變量 - 一切總是在一個包命名空間,以便作出全局變量是不太這樣一個大問題,如如C.

語言
package main 

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

// Globals 
var (
    in = bufio.NewScanner(os.Stdin) 
) 

func prompt(format string) string { 
    fmt.Print(format) 
    in.Scan() 
    return in.Text() 
} 

func greet() { 
    name := prompt("enter name: ") 
    fmt.Printf("Hello %s!\n", name) 
} 

func humor() { 
    color := prompt("enter favorite color: ") 
    fmt.Printf("I like %s too!\n", color) 
} 

func main() { 
    greet() 
    humor() 
}