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。
golang 格式化輸入輸出
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.