基礎(chǔ)知識(shí) - Golang 中的格式化輸入輸出

【格式化輸出】

// 格式化輸出:將 arg 列表中的 arg 轉(zhuǎn)換為字符串輸出

// 使用動(dòng)詞 v 格式化 arg 列表挂捅,非字符串元素之間添加空格
Print(arg列表)
// 使用動(dòng)詞 v 格式化 arg 列表,所有元素之間添加空格鲁冯,結(jié)尾添加換行符
Println(arg列表)
// 使用格式字符串格式化 arg 列表
Printf(格式字符串, arg列表)

// Print 類函數(shù)會(huì)返回已處理的 arg 數(shù)量和遇到的錯(cuò)誤信息丘薛。


【格式字符串】

格式字符串由普通字符和占位符組成腻暮,例如:

"abc%+ #8.3[3]vdef"

其中 abc 和 def 是普通字符讥珍,其它部分是占位符,占位符以 % 開(kāi)頭(注:%% 將被轉(zhuǎn)義為一個(gè)普通的 % 符號(hào)毁菱,這個(gè)不算開(kāi)頭)米死,以動(dòng)詞結(jié)尾,格式如下:

%[旗標(biāo)][寬度][.精度][arg索引]動(dòng)詞

方括號(hào)中的內(nèi)容可以省略贮庞。


【旗標(biāo)】

旗標(biāo)有以下幾種:

  • :對(duì)于數(shù)值類型總是輸出正負(fù)號(hào)(其它用法在動(dòng)詞部分說(shuō)明)峦筒。
  • :在右邊進(jìn)行寬度填充,而不是默認(rèn)的左邊窗慎。

空格:對(duì)于數(shù)值類型的正數(shù)物喷,保留一個(gè)空白的符號(hào)位(其它用法在動(dòng)詞部分說(shuō)明)。

0 :用 0 進(jìn)行寬度填充而不用空格遮斥,對(duì)于數(shù)值類型峦失,符號(hào)將被移到所有 0 的前面。

:相關(guān)用法在動(dòng)詞部分說(shuō)明术吗。

其中 "0" 和 "-" 不能同時(shí)使用尉辑,優(yōu)先使用 "-" 而忽略 "0"。


【寬度和精度】

“寬度”和“精度”都可以寫(xiě)成以下三種形式:

數(shù)值 | * | arg索引*

其中“數(shù)值”表示使用指定的數(shù)值作為寬度值或精度值较屿,“”表示使用當(dāng)前正在處理的 arg 的值作為寬度值或精度值隧魄,如果這樣的話,要格式化的 arg 將自動(dòng)跳轉(zhuǎn)到下一個(gè)隘蝎〉唐鳎“arg索引”表示使用指定 arg 的值作為寬度值或精度值,如果這樣的話末贾,要格式化的 arg 將自動(dòng)跳轉(zhuǎn)到指定 arg 的下一個(gè)。

寬度值:用于設(shè)置最小寬度整吆。

精度值:對(duì)于浮點(diǎn)型拱撵,用于控制小數(shù)位數(shù),對(duì)于字符串或字節(jié)數(shù)組表蝙,用于控制字符數(shù)量(不是字節(jié)數(shù)量)拴测。

對(duì)于浮點(diǎn)型而言,動(dòng)詞 g/G 的精度值比較特殊府蛇,在適當(dāng)?shù)那闆r下集索,g/G 會(huì)設(shè)置總有效數(shù)字,而不是小數(shù)位數(shù)。


【arg 索引】

“arg索引”由中括號(hào)和 arg 序號(hào)組成(就像上面示例中的 [3])务荆,用于指定當(dāng)前要處理的 arg 的序號(hào)妆距,序號(hào)從 1 開(kāi)始:

'[' + arg序號(hào) + ']'


【動(dòng)詞】

“動(dòng)詞”不能省略,不同的數(shù)據(jù)類型支持的動(dòng)詞不一樣函匕。


[通用動(dòng)詞]

v:默認(rèn)格式娱据,不同類型的默認(rèn)格式如下:

布爾型:t
  整 型:d
  浮點(diǎn)型:g
  復(fù)數(shù)型:g
  字符串:s
  通 道:p
  指 針:p

v:默認(rèn)格式,以符合 Go 語(yǔ)法的方式輸出盅惜。特殊類型的 Go 語(yǔ)法格式如下:

無(wú)符號(hào)整型:x

T:輸出 arg 的類型而不是值(使用 Go 語(yǔ)法格式)中剩。


[布爾型]

t:輸出 true 或 false 字符串。


[整型]

b/o/d:輸出 2/8/10 進(jìn)制格式
x/X :輸出 16 進(jìn)制格式(小寫(xiě)/大寫(xiě))
c :輸出數(shù)值所表示的 Unicode 字符
q :輸出數(shù)值所表示的 Unicode 字符(帶單引號(hào))抒寂。對(duì)于無(wú)法顯示的字符结啼,將輸出其轉(zhuǎn)義字符。
U :輸出 Unicode 碼點(diǎn)(例如 U+1234屈芜,等同于字符串 "U+%04X" 的顯示結(jié)果)

對(duì)于 o/x/X:
如果使用 "#" 旗標(biāo)郊愧,則會(huì)添加前導(dǎo) 0 或 0x。

對(duì)于 U:
如果使用 "#" 旗標(biāo)沸伏,則會(huì)在 Unicode 碼點(diǎn)后面添加相應(yīng)的 '字符'(前提是該字符必須可顯示)


[浮點(diǎn)型和復(fù)數(shù)型]

b :科學(xué)計(jì)數(shù)法(以 2 為底)
e/E:科學(xué)計(jì)數(shù)法(以 10 為底糕珊,小寫(xiě) e/大寫(xiě) E)
f/F:普通小數(shù)格式(兩者無(wú)區(qū)別)
g/G:大指數(shù)(指數(shù) >= 6)使用 %e/%E,其它情況使用 %f/%F


[字符串或字節(jié)切片]

s :普通字符串
q :雙引號(hào)引起來(lái)的 Go 語(yǔ)法字符串
x/X:十六進(jìn)制編碼(小寫(xiě)/大寫(xiě)毅糟,以字節(jié)為元素進(jìn)行編碼红选,而不是字符)

對(duì)于 q:
如果使用了 "+" 旗標(biāo),則將所有非 ASCII 字符都進(jìn)行轉(zhuǎn)義處理姆另。
如果使用了 "#" 旗標(biāo)喇肋,則輸出反引號(hào)引起來(lái)的字符串(前提是
字符串中不包含任何制表符以外的控制字符,否則忽略 # 旗標(biāo))

對(duì)于 x/X:
如果使用了 " " 旗標(biāo)迹辐,則在每個(gè)元素之間添加空格蝶防。
如果使用了 "#" 旗標(biāo),則在十六進(jìn)制格式之前添加 0x 前綴明吩。


[指針類型]

p :帶 0x 前綴的十六進(jìn)制地址值间学。

p:不帶 0x 前綴的十六進(jìn)制地址值。


[符合類型]

復(fù)合類型將使用不同的格式輸出印荔,格式如下:

結(jié) 構(gòu) 體:{字段1 字段2 ...}
數(shù)組或切片:[元素0 元素1 ...]
映   射:map[鍵1:值1 鍵2:值2 ...]

指向符合元素的指針:&{}, &[], &map[]

復(fù)合類型本身沒(méi)有動(dòng)詞低葫,動(dòng)詞將應(yīng)用到復(fù)合類型的元素上。

結(jié)構(gòu)體可以使用 "+v" 同時(shí)輸出字段名仍律。


【完整示例】

package main

import "fmt"

func main() {
    // 旗標(biāo)嘿悬、寬度、精度水泉、索引
    fmt.Printf("|%0+- #[1]*.[2]*[3]d|%0+- #[1]*.[2]*[4]d|\n", 8, 4, 32, 64)

    // 浮點(diǎn)型精度
    fmt.Printf("|%f|%8.4f|%8.f|%.4f|%.f|\n", 3.2, 3.2, 3.2, 3.2, 3.2)
    fmt.Printf("|%.3f|%.3g|\n", 12.345678, 12.345678)
    fmt.Printf("|%.2f|\n", 12.345678+12.345678i)

    // 字符串精度
    s := "你好世界善涨!"
    fmt.Printf("|%s|%8.2s|%8.s|%.2s|%.s|\n", s, s, s, s, s)
    fmt.Printf("|%x|%8.2x|%8.x|%.2x|%.x|\n", s, s, s, s, s)

    // 帶引號(hào)字符串
    s1 := "Hello 世界!"       // CanBackquote
    s2 := "Hello\n世界!"      // !CanBackquote
    fmt.Printf("%q\n", s1)  // 雙引號(hào)
    fmt.Printf("%#q\n", s1) // 反引號(hào)成功
    fmt.Printf("%#q\n", s2) // 反引號(hào)失敗
    fmt.Printf("%+q\n", s2) // 僅包含 ASCII 字符

    // Unicode 碼點(diǎn)
    fmt.Printf("%U, %#U\n", '好', '好')
    fmt.Printf("%U, %#U\n", '\n', '\n')

    // 接口類型將輸出其內(nèi)部包含的值
    var i interface{} = struct {
        name string
        age  int
    }{"AAA", 20}
    fmt.Printf("%v\n", i)  // 只輸出字段值
    fmt.Printf("%+v\n", i) // 同時(shí)輸出字段名
    fmt.Printf("%#v\n", i) // Go 語(yǔ)法格式

    // 輸出類型
    fmt.Printf("%T\n", i)
}

【注意】

1窒盐、如果 arg 是一個(gè)反射值,則該 arg 將被它所持有的具體值所取代钢拧。

2蟹漓、如果 arg 實(shí)現(xiàn)了 Formatter 接口,將調(diào)用它的 Format 方法完成格式化娶靡。

3牧牢、如果 v 動(dòng)詞使用了 # 旗標(biāo)(%#v),并且 arg 實(shí)現(xiàn)了 GoStringer 接口姿锭,將調(diào)用它的 GoString 方法完成格式化塔鳍。

如果格式化操作指定了字符串相關(guān)的動(dòng)詞(比如 %s、%q呻此、%v轮纫、%x、%X)焚鲜,接下來(lái)的兩條規(guī)則將適用:

4掌唾。如果 arg 實(shí)現(xiàn)了 error 接口,將調(diào)用它的 Error 方法完成格式化忿磅。

5糯彬。如果 arg 實(shí)現(xiàn)了 string 接口,將調(diào)用它的 String 方法完成格式化葱她。

在實(shí)現(xiàn)格式化相關(guān)接口的時(shí)候撩扒,要避免無(wú)限遞歸的情況,比如:

type X string

func (x X) String() string {
return Sprintf("<%s>", x)
}

在格式化之前吨些,要先轉(zhuǎn)換數(shù)據(jù)類型搓谆,這樣就可以避免無(wú)限遞歸:

func (x X) String() string {
return Sprintf("<%s>", string(x))
}

無(wú)限遞歸也可能發(fā)生在自引用數(shù)據(jù)類型上面,比如一個(gè)切片的元素引用了切片自身豪墅。這種情況比較罕見(jiàn)泉手,比如:

a := make([]interface{}, 1)
a[0] = a
fmt.Println(a)


【格式化輸入】

// 格式化輸入:從輸入端讀取字符串(以空白分隔的值的序列),
// 并解析為具體的值存入相應(yīng)的 arg 中偶器,arg 必須是變量地址斩萌。
// 字符串中的連續(xù)空白視為單個(gè)空白,換行符根據(jù)不同情況處理屏轰。
// \r\n 被當(dāng)做 \n 處理颊郎。

// 以動(dòng)詞 v 解析字符串,換行視為空白
Scan(arg列表)
// 以動(dòng)詞 v 解析字符串亭枷,換行結(jié)束解析
Scanln(arg列表)
// 根據(jù)格式字符串中指定的格式解析字符串
// 格式字符串中的換行符必須和輸入端的換行符相匹配。
Scanf(格式字符串, arg列表)

// Scan 類函數(shù)會(huì)返回已處理的 arg 數(shù)量和遇到的錯(cuò)誤信息搀崭。


【格式字符串】

格式字符串類似于 Printf 中的格式字符串叨粘,但下面的動(dòng)詞和旗標(biāo)例外:

p :無(wú)效
T :無(wú)效
e/E/f/F/g/G:功能相同猾编,都是掃描浮點(diǎn)數(shù)或復(fù)數(shù)
s/v :對(duì)字符串而言,掃描一個(gè)被空白分隔的子串

/+ :無(wú)效

對(duì)于整型 arg 而言升敲,v 動(dòng)詞可以掃描帶有前導(dǎo) 0 或 0x 的八進(jìn)制或十六進(jìn)制數(shù)值答倡。

寬度被用來(lái)指定最大掃描寬度(不會(huì)跨越空格),精度不被支持驴党。

如果 arg 實(shí)現(xiàn)了 Scanner 接口瘪撇,將調(diào)用它的 Scan 方法掃描相應(yīng)數(shù)據(jù)。只有基礎(chǔ)類型和實(shí)現(xiàn)了 Scanner 接口的類型可以使用 Scan 類方法進(jìn)行掃描港庄。


【完整示例】

// 對(duì)于 Scan 而言倔既,回車視為空白
func main() {
    a, b, c := "", 0, false
    fmt.Scan(&a, &b, &c)
    fmt.Println(a, b, c)
    // 在終端執(zhí)行后,輸入 abc 1 回車 t 回車
    // 結(jié)果 abc 1 true
}

// 整型變量也可以解析八進(jìn)制和十六進(jìn)制
func main() {
    a, b, c := "", 0, false
    fmt.Scanln(&a, &b, &c)
    fmt.Println(a, b, c)
    // 在終端執(zhí)行后鹏氧,輸入 def 0x20 T 回車
    // 結(jié)果 def 32 true
}

// 格式字符串可以指定寬度
func main() {
    a, b, c := "", 0, false
    fmt.Scanf("%4s%d%t", &a, &b, &c)
    fmt.Println(a, b, c)
    // 在終端執(zhí)行后渤涌,輸入 1234567true 回車
    // 結(jié)果 1234 567 true
}

// 指定寬度不能跨越空白
func main() {
    a, b, c := "", 0, false
    fmt.Scanf("%4s%d%t", &a, &b, &c)
    fmt.Println(a, b, c)
    // 在終端執(zhí)行后,輸入 12 34567True 回車
    // 結(jié)果 12 34567 true
}

// %c 總是匹配下一個(gè)字符把还,包括空格
func main() {
    a, b, c := "", 0, 0
    fmt.Scanf("%s%c%d", &a, &b, &c)
    fmt.Println(a, b, c)
    // 在終端執(zhí)行后实蓬,輸入 abc 1 回車
    // 結(jié)果 abc 32 1
}

【注意】

連續(xù)調(diào)用 FScan 可能會(huì)丟失數(shù)據(jù),因?yàn)?FScan 中使用了 UnreadRune 對(duì)讀取的數(shù)據(jù)進(jìn)行撤銷吊履,而參數(shù) io.Reader 只有 Read 方法安皱,不支持撤銷。比如:

package main

import (
    "fmt"
    "io"
    "strings"
)

// 實(shí)現(xiàn) Reader 接口的字符串類型
type stringReader string

func (r *stringReader) Read(b []byte) (n int, err error) {
    n = copy(b, *r)
    *r = (*r)[n:]
    if n == 0 {
        err = io.EOF
    }
    return
}

func main() {
    // 下面的操作將丟失字符 a
    s := stringReader("123abcd")
    a, b := 0, ""
    fmt.Fscan(&s, &a)
    fmt.Fscan(&s, &b)
    fmt.Println(a, b) // 123 bcd

    // 如果使用 strings.NewReader 則不會(huì)丟失艇炎,因?yàn)樗鼘?shí)現(xiàn)了 RuneScanner 接口
    r := strings.NewReader("123abcd")
    c, d := 0, ""
    fmt.Fscan(r, &c)
    fmt.Fscan(r, &d)
    fmt.Println(c, d) // 123 abcd
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酌伊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子冕臭,更是在濱河造成了極大的恐慌腺晾,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辜贵,死亡現(xiàn)場(chǎng)離奇詭異悯蝉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)托慨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)鼻由,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人厚棵,你說(shuō)我怎么就攤上這事蕉世。” “怎么了婆硬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵狠轻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我彬犯,道長(zhǎng)向楼,這世上最難降的妖魔是什么查吊? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮湖蜕,結(jié)果婚禮上逻卖,老公的妹妹穿的比我還像新娘。我一直安慰自己昭抒,他們只是感情好评也,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著灭返,像睡著了一般盗迟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婆殿,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天诈乒,我揣著相機(jī)與錄音,去河邊找鬼婆芦。 笑死怕磨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的消约。 我是一名探鬼主播肠鲫,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼或粮!你這毒婦竟也來(lái)了导饲?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤氯材,失蹤者是張志新(化名)和其女友劉穎渣锦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體氢哮,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡袋毙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了冗尤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片听盖。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖裂七,靈堂內(nèi)的尸體忽然破棺而出皆看,到底是詐尸還是另有隱情,我是刑警寧澤背零,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布腰吟,位于F島的核電站,受9級(jí)特大地震影響徙瓶,放射性物質(zhì)發(fā)生泄漏毛雇。R本人自食惡果不足惜录语,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望禾乘。 院中可真熱鬧,春花似錦虽缕、人聲如沸始藕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)伍派。三九已至,卻和暖如春剩胁,著一層夾襖步出監(jiān)牢的瞬間诉植,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工昵观, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晾腔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓啊犬,卻偏偏與公主長(zhǎng)得像灼擂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子觉至,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 【格式化輸出】 // 格式化輸出:將 arg 列表中的 arg 轉(zhuǎn)換為字符串輸出 // 使用動(dòng)詞 v 格式化 ar...
    小流歌_閱讀 1,151評(píng)論 0 0
  • 本文為個(gè)人學(xué)習(xí)記錄剔应,對(duì)原作者文章進(jìn)行了一些排版調(diào)整和修改,原文地址 ===> GoLove 的博客 格式化輸出:將...
    Chaz6chez閱讀 1,930評(píng)論 0 1
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,380評(píng)論 0 5
  • 一语御、Python簡(jiǎn)介和環(huán)境搭建以及pip的安裝 4課時(shí)實(shí)驗(yàn)課主要內(nèi)容 【Python簡(jiǎn)介】: Python 是一個(gè)...
    _小老虎_閱讀 5,744評(píng)論 0 10
  • 一峻贮、基礎(chǔ)知識(shí):1、JVM应闯、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機(jī)...
    殺小賊閱讀 2,378評(píng)論 0 4