golang 格式化輸入輸出

fmt 包實現了格式化 I/O 函數,類似於 C 的 printf 和 scanf。格式“佔位符”衍生自 C,但比 C 更簡單。
【打印】
佔位符:
[一般]
%v	相應值的默認格式。在打印結構體時,“加號”標記(%+v)會添加字段名
%#v	相應值的 Go 語法表示
%T	相應值的類型的 Go 語法表示
%%	字面上的百分號,並非值的佔位符
[布爾]
%t	單詞 true 或 false。
[整數]
%b	二進制表示
%c	相應 Unicode 碼點所表示的字符
%d	十進制表示
%o	八進制表示
%q	單引號圍繞的字符字面值,由 Go 語法安全地轉義
%x	十六進制表示,字母形式爲小寫 a-f
%X	十六進制表示,字母形式爲大寫 A-F
%U	Unicode 格式:U+1234,等同於 "U+%04X"
[浮點數及其複合構成]
%b	無小數部分的,指數爲二的冪的科學計數法,與 strconv.FormatFloat 的 'b' 轉換格式一致。例如 -123456p-78
%e	科學計數法,例如 -1234.456e+78
%E	科學計數法,例如 -1234.456E+78
%f	有小數點而無指數,例如 123.456
%g	根據情況選擇 %e 或 %f 以產生更緊湊的(無末尾的 0)輸出
%G	根據情況選擇 %E 或 %f 以產生更緊湊的(無末尾的 0)輸出
[字符串與字節切片]
%s	字符串或切片的無解譯字節
%q	雙引號圍繞的字符串,由 Go 語法安全地轉義
%x	十六進制,小寫字母,每字節兩個字符
%X	十六進制,大寫字母,每字節兩個字符
[指針]
%p	十六進制表示,前綴 0x
[注意]
這裏沒有 'u' 標記。若整數爲無符號類型,他們就會被打印成無符號的。類似地, 這裏也不需要指定操作數的大小(int8,int64)。
寬度與精度的控制格式以 Unicode 碼點爲單位。(這點與 C 的 printf 不同, 它以字節數爲單位。)二者或其中之一均可用字符 '*' 表示, 此時它們的值會從下一個操作數中獲取,該操作數的類型必須爲 int。
// 寬度與精度的控制以 Unicode 碼點爲單位
fmt.Printf("\"%8s\"\n", "123456") // 最大長度爲 8
// "  123456"
fmt.Printf("\"%8s\"\n", "你好")   // 最大長度爲 8
// "      你好"
// 寬度與精度均可用字符 '*' 表示
fmt.Printf("%0*.*f \n", 8, 3, 13.25) // 總長度 8,小數位數 3
fmt.Printf("%08.3f \n", 13.25)       // 總長度 8,小數位數 3
// 0013.250
對數值而言,寬度爲該數值佔用區域的最小寬度;精度爲小數點之後的位數。 但對於 %g/%G 而言,精度爲所有數字的總數。例如,對於 123.45,格式 %6.2f 會打印 123.45,而 %.4g 會打印 123.5。%e 和 %f 的默認精度爲 6;但對於 %g 而言,它的默認精度爲確定該值所必須的最小位數。
對大多數值而言,寬度爲輸出的最小字符數,如果必要的話會爲已格式化的形式填充空格。對字符串而言,精度爲輸出的最大字符數,如果必要的話會直接截斷。
// 寬度與精度標記字符串
fmt.Printf("%8q", "ABC")         // 最小長度爲 8(包括 %q 的引號字符)
//    "ABC"
fmt.Printf("%.8q", "1234567890") // 最大長度爲 8(不包括 %q 的引號字符)
// "12345678"
[其它標記]
+	總打印數值的正負號;對於 %q(%+q)保證只輸出 ASCII 編碼的字符。
-	在右側而非左側填充空格(左對齊該區域)
#	備用格式:爲八進制添加前導 0(%#o),爲十六進制添加前導 0x(%#x)或
0X(%#X),爲 %p(%#p)去掉前導 0x;如果可能的話,%q(%#q)會打印原始(即反引號圍繞的)字符串;如果是可打印字符,%U(%#U)會寫出該字符的 Unicode 編碼形式(如字符 x 會被打印成 U+0078 'x')。
' '	(空格)爲數值中省略的正負號留出空白(% d);以十六進制(% x, % X)打印字符串或切片時,在字節之間用空格隔開:
fmt.Printf("% x\n", "Hello")
// 48 65 6c 6c 6f
0	填充前導的 0 而非空格;對於數字,這會將填充移到正負號之後
[注意]
標記有時會被佔位符忽略,所以不要指望它們。例如十進制沒有備用格式,因此 %#d 與 %d 的行爲相同。
對於每一個 Printf 類的函數,都有一個 Print 函數,該函數不接受任何格式化, 它等價於對每一個操作數都應用 %v。另一個變參函數 Println 會在操作數之間插入空白, 並在末尾追加一個換行符。
不考慮佔位符的話,如果操作數是接口值,就會使用其內部的具體值,而非接口本身。 因此:
var i interface{} = 23
fmt.Printf("%v\n", i)
// 會打印 23
若一個操作數實現了 Formatter 接口,該接口就能更好地用於控制格式化。
若其格式(它對於 Println 等函數是隱式的 %v)對於字符串是有效的(%s %q %v %x %X),以下兩條規則也適用:
1。若一個操作數實現了 error 接口,Error 方法就能將該對象轉換爲字符串,隨後會根據佔位符的需要進行格式化。
2。若一個操作數實現了 String() string 方法,該方法能將該對象轉換爲字符串,隨後會根據佔位符的需要進行格式化。
爲避免以下這類遞歸的情況:
type X string
func (x X) String() string { return Sprintf("<%s>", x) }
需要在遞歸前轉換該值:
func (x X) String() string { return Sprintf("<%s>", string(x)) }
[格式化錯誤]
如果給佔位符提供了無效的實參(例如將一個字符串提供給 %d),所生成的字符串會包含該問題的描述,如下例所示:
類型錯誤或佔位符未知:%!verb(type=value)
Printf("%d", hi)
// %!d(string=hi)
實參太多:%!(EXTRA type=value)
Printf("hi", "guys")
// hi%!(EXTRA string=guys)
實參太少:%!verb(MISSING)
Printf("hi%d")
// hi %!d(MISSING)
寬度或精度不是 int 類型:%!(BADWIDTH)或 %!(BADPREC)
Printf("%*s", 4.5, "hi")
// %!(BADWIDTH)hi
Printf("%.*s", 4.5, "hi")
// %!(BADPREC)hi
所有錯誤都始於“%!”,有時緊跟着單個字符(佔位符),並以小括號括住的描述結尾。
【掃描】
一組類似的函數通過掃描已格式化的文本來產生值。Scan、Scanf 和 Scanln 從 os.Stdin 中讀取;Fscan、Fscanf 和 Fscanln 從指定的 io.Reader 中讀取; Sscan、Sscanf 和 Sscanln 從實參字符串中讀取。Scanln、Fscanln 和 Sscanln 在換行符處停止掃描,且需要條目緊隨換行符之後;Scanf、Fscanf 和 Sscanf 需要輸入換行符來匹配格式中的換行符;其它函數則將換行符視爲空格。
Scanf、Fscanf 和 Sscanf 根據格式字符串解析實參,類似於 Printf。例如,%x 會將一個整數掃描爲十六進制數,而 %v 則會掃描該值的默認表現格式。
格式化行爲類似於 Printf,但也有如下例外:
%p 沒有實現
%T 沒有實現
%e %E %f %F %g %G 都完全等價,且可掃描任何浮點數或複合數值
%s 和 %v 在掃描字符串時會將其中的空格作爲分隔符
標記 # 和 + 沒有實現
在使用 %v 佔位符掃描整數時,可接受友好的進制前綴 0(八進制)和 0x(十六進制)。
寬度被解釋爲輸入的文本(%5s 意爲最多從輸入中讀取 5 個符文來掃描成字符串),而掃描函數則沒有精度的語法(沒有 %5.2f,只有 %5f)。
當以某種格式進行掃描時,無論在格式中還是在輸入中,所有非空的連續空白字符 (除換行符外)都等價於單個空格。由於這種限制,格式字符串文本必須匹配輸入的文本,如果不匹配,掃描過程就會停止,並返回已掃描的實參數。
在所有的掃描參數中,若一個操作數實現了 Scan 方法(即它實現了 Scanner 接口),該操作數將使用該方法掃描其文本。此外,若已掃描的實參數少於所提供的實參數,就會返回一個錯誤。
所有需要被掃描的實參都必須是基本類型或實現了 Scanner 接口的類型。
注意:Fscan 等函數會從輸入中多讀取一個字符(符文),因此,如果循環調用掃描函數,可能會跳過輸入中的某些數據。一般只有在輸入的數據中沒有空白符時該問題纔會出現。若提供給 Fscan 的讀取器實現了 ReadRune,就會用該方法讀取字符。若此讀取器還實現了 UnreadRune 方法,就會用該方法保存字符,而連續的調用將不會丟失數據。若要爲沒有 ReadRune 和 UnreadRune 方法的讀取器加上這些功能,需使用 bufio.NewReader。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章