// Print 將參數(shù)列表 a 中的各個(gè)參數(shù)轉(zhuǎn)換為字符串并寫入到標(biāo)準(zhǔn)輸出中已慢。
// 非字符串參數(shù)之間會(huì)添加空格入挣,返回寫入的字節(jié)數(shù)移宅。
func Print(a ...interface{}) (n int, err error)
// Println 功能類似 Print,只不過(guò)最后會(huì)添加一個(gè)換行符泡徙。
// 所有參數(shù)之間會(huì)添加空格橱鹏,返回寫入的字節(jié)數(shù)。
func Println(a ...interface{}) (n int, err error)
// Printf 將參數(shù)列表 a 填寫到格式字符串 format 的占位符中堪藐。
// 填寫后的結(jié)果寫入到標(biāo)準(zhǔn)輸出中莉兰,返回寫入的字節(jié)數(shù)。
func Printf(format string, a ...interface{}) (n int, err error)
// 功能同上面三個(gè)函數(shù)礁竞,只不過(guò)將轉(zhuǎn)換結(jié)果寫入到 w 中糖荒。
func Fprint(w io.Writer, a ...interface{}) (n int, err error)
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
// 功能同上面三個(gè)函數(shù),只不過(guò)將轉(zhuǎn)換結(jié)果以字符串形式返回模捂。
func Sprint(a ...interface{}) string
func Sprintln(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
// 功能同 Sprintf捶朵,只不過(guò)結(jié)果字符串被包裝成了 error 類型。
func Errorf(format string, a ...interface{}) error
// 示例
func main() {
fmt.Print("a", "b", 1, 2, 3, "c", "d", "\n")
fmt.Println("a", "b", 1, 2, 3, "c", "d")
fmt.Printf("ab %d %d %d cd\n", 1, 2, 3)
// ab1 2 3cd
// a b 1 2 3 c d
// ab 1 2 3 cd
if err := percent(30, 70, 90, 160); err != nil {
fmt.Println(err)
}
// 30%
// 70%
// 90%
// 數(shù)值 160 超出范圍(100)
}
func percent(i ...int) error {
for _, n := range i {
if n > 100 {
return fmt.Errorf("數(shù)值 %d 超出范圍(100)", n)
}
fmt.Print(n, "%\n")
}
return nil
}
// Formatter 由自定義類型實(shí)現(xiàn)狂男,用于實(shí)現(xiàn)該類型的自定義格式化過(guò)程综看。
// 當(dāng)格式化器需要格式化該類型的變量時(shí),會(huì)調(diào)用其 Format 方法岖食。
type Formatter interface {
// f 用于獲取占位符的旗標(biāo)寓搬、寬度、精度等信息县耽,也用于輸出格式化的結(jié)果
// c 是占位符中的動(dòng)詞
Format(f State, c rune)
}
// 由格式化器(Print 之類的函數(shù))實(shí)現(xiàn)句喷,用于給自定義格式化過(guò)程提供信息
type State interface {
// Formatter 通過(guò) Write 方法將格式化結(jié)果寫入格式化器中,以便輸出兔毙。
Write(b []byte) (ret int, err error)
// Formatter 通過(guò) Width 方法獲取占位符中的寬度信息及其是否被設(shè)置唾琼。
Width() (wid int, ok bool)
// Formatter 通過(guò) Precision 方法獲取占位符中的精度信息及其是否被設(shè)置。
Precision() (prec int, ok bool)
// Formatter 通過(guò) Flag 方法獲取占位符中的旗標(biāo)[+- 0#]是否被設(shè)置澎剥。
Flag(c int) bool
}
// Stringer 由自定義類型實(shí)現(xiàn)锡溯,用于實(shí)現(xiàn)該類型的自定義格式化過(guò)程。
// 當(dāng)格式化器需要輸出該類型的字符串格式時(shí)就會(huì)調(diào)用其 String 方法哑姚。
type Stringer interface {
String() string
}
// Stringer 由自定義類型實(shí)現(xiàn)祭饭,用于實(shí)現(xiàn)該類型的自定義格式化過(guò)程。
// 當(dāng)格式化器需要輸出該類型的 Go 語(yǔ)法字符串(%#v)時(shí)就會(huì)調(diào)用其 String 方法叙量。
type GoStringer interface {
GoString() string
}
// 示例
type Ustr string
func (us Ustr) String() string {
return strings.ToUpper(string(us))
}
func (us Ustr) GoString() string {
return `"` + strings.ToUpper(string(us)) + `"`
}
func (u Ustr) Format(f fmt.State, c rune) {
write := func(s string) {
f.Write([]byte(s))
}
switch c {
case 'm', 'M':
write("旗標(biāo):[")
for s := "+- 0#"; len(s) > 0; s = s[1:] {
if f.Flag(int(s[0])) {
write(s[:1])
}
}
write("]")
if v, ok := f.Width(); ok {
write(" | 寬度:" + strconv.FormatInt(int64(v), 10))
}
if v, ok := f.Precision(); ok {
write(" | 精度:" + strconv.FormatInt(int64(v), 10))
}
case 's', 'v': // 如果使用 Format 函數(shù)倡蝙,則必須自己處理所有格式,包括 %#v
if c == 'v' && f.Flag('#') {
write(u.GoString())
} else {
write(u.String())
}
default: // 如果使用 Format 函數(shù)绞佩,則必須自己處理默認(rèn)輸出
write("無(wú)效格式:" + string(c))
}
}
func main() {
u := Ustr("Hello World!")
// "-" 標(biāo)記和 "0" 標(biāo)記不能同時(shí)存在
fmt.Printf("%-+ 0#8.5m\n", u) // 旗標(biāo):[+- #] | 寬度:8 | 精度:5
fmt.Printf("%+ 0#8.5M\n", u) // 旗標(biāo):[+ 0#] | 寬度:8 | 精度:5
fmt.Println(u) // HELLO WORLD!
fmt.Printf("%s\n", u) // HELLO WORLD!
fmt.Printf("%#v\n", u) // "HELLO WORLD!"
fmt.Printf("%d\n", u) // 無(wú)效格式:d
}
// Scan 從標(biāo)準(zhǔn)輸入中讀取數(shù)據(jù)寺鸥,并將數(shù)據(jù)用空白分割并解析后存入 a 提供
// 的變量中(換行符會(huì)被當(dāng)作空白處理),變量必須以指針傳入品山。
// 當(dāng)讀到 EOF 或所有變量都填寫完畢則停止掃描胆建。
// 返回成功解析的參數(shù)數(shù)量。
func Scan(a ...interface{}) (n int, err error)
// Scanln 和 Scan 類似肘交,只不過(guò)遇到換行符就停止掃描笆载。
func Scanln(a ...interface{}) (n int, err error)
// Scanf 從標(biāo)準(zhǔn)輸入中讀取數(shù)據(jù),并根據(jù)格式字符串 format 對(duì)數(shù)據(jù)進(jìn)行解析涯呻,
// 將解析結(jié)果存入?yún)?shù) a 所提供的變量中凉驻,變量必須以指針傳入。
// 輸入端的換行符必須和 format 中的換行符相對(duì)應(yīng)(如果格式字符串中有換行
// 符魄懂,則輸入端必須輸入相應(yīng)的換行符)沿侈。
// 占位符 %c 總是匹配下一個(gè)字符,包括空白市栗,比如空格符缀拭、制表符、換行符填帽。
// 返回成功解析的參數(shù)數(shù)量蛛淋。
func Scanf(format string, a ...interface{}) (n int, err error)
// 功能同上面三個(gè)函數(shù),只不過(guò)從 r 中讀取數(shù)據(jù)篡腌。
func Fscan(r io.Reader, a ...interface{}) (n int, err error)
func Fscanln(r io.Reader, a ...interface{}) (n int, err error)
func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
// 功能同上面三個(gè)函數(shù)褐荷,只不過(guò)從 str 中讀取數(shù)據(jù)。
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)
// 示例
// 對(duì)于 Scan 而言嘹悼,回車視為空白
func main() {
a, b, c := "", 0, false
fmt.Scan(&a, &b, &c)
fmt.Println(a, b, c)
// 在終端執(zhí)行后叛甫,輸入 abc 1 回車 true 回車
// 結(jié)果 abc 1 true
}
// 對(duì)于 Scanln 而言层宫,回車結(jié)束掃描
func main() {
a, b, c := "", 0, false
fmt.Scanln(&a, &b, &c)
fmt.Println(a, b, c)
// 在終端執(zhí)行后,輸入 abc 1 true 回車
// 結(jié)果 abc 1 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
}
// Scanner 由自定義類型實(shí)現(xiàn)萌腿,用于實(shí)現(xiàn)該類型的自定義掃描過(guò)程。
// 當(dāng)掃描器需要解析該類型的數(shù)據(jù)時(shí)抖苦,會(huì)調(diào)用其 Scan 方法毁菱。
type Scanner interface {
// state 用于獲取占位符中的寬度信息,也用于從掃描器中讀取數(shù)據(jù)進(jìn)行解析锌历。
// verb 是占位符中的動(dòng)詞
Scan(state ScanState, verb rune) error
}
// 由掃描器(Scan 之類的函數(shù))實(shí)現(xiàn)贮庞,用于給自定義掃描過(guò)程提供數(shù)據(jù)和信息。
type ScanState interface {
// ReadRune 從掃描器中讀取一個(gè)字符,如果用在 Scanln 類的掃描器中,
// 則該方法會(huì)在讀到第一個(gè)換行符之后或讀到指定寬度之后返回 EOF拧揽。
// 返回“讀取的字符”和“字符編碼所占用的字節(jié)數(shù)”
ReadRune() (r rune, size int, err error)
// UnreadRune 撤消最后一次的 ReadRune 操作浆兰,
// 使下次的 ReadRune 操作得到與前一次 ReadRune 相同的結(jié)果。
UnreadRune() error
// SkipSpace 為 Scan 方法提供跳過(guò)開頭空白的能力。
// 根據(jù)掃描器的不同(Scan 或 Scanln)決定是否跳過(guò)換行符。
SkipSpace()
// Token 用于從掃描器中讀取符合要求的字符串,
// Token 從掃描器中讀取連續(xù)的符合 f(c) 的字符 c伏伐,準(zhǔn)備解析。
// 如果 f 為 nil晕拆,則使用 !unicode.IsSpace(c) 代替 f(c)藐翎。
// skipSpace:是否跳過(guò)開頭的連續(xù)空白。返回讀取到的數(shù)據(jù)实幕。
// 注意:token 指向共享的數(shù)據(jù)吝镣,下次的 Token 操作可能會(huì)覆蓋本次的結(jié)果。
Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
// Width 返回占位符中的寬度值以及寬度值是否被設(shè)置
Width() (wid int, ok bool)
// 因?yàn)樯厦鎸?shí)現(xiàn)了 ReadRune 方法昆庇,所以 Read 方法永遠(yuǎn)不應(yīng)該被調(diào)用末贾。
// 一個(gè)好的 ScanState 應(yīng)該讓 Read 直接返回相應(yīng)的錯(cuò)誤信息。
Read(buf []byte) (n int, err error)
}
// 示例
type Ustr string
func (u *Ustr) Scan(state fmt.ScanState, verb rune) (err error) {
var s []byte
switch verb {
case 'S':
s, err = state.Token(true, func(c rune) bool { return 'A' <= c && c <= 'Z' })
if err != nil {
return
}
case 's', 'v':
s, err = state.Token(true, func(c rune) bool { return 'a' <= c && c <= 'z' })
if err != nil {
return
}
default:
return fmt.Errorf("無(wú)效格式:%c", verb)
}
*u = Ustr(s)
return nil
}
func main() {
var a, b, c, d, e Ustr
n, err := fmt.Scanf("%3S%S%3s%2v%x", &a, &b, &c, &d, &e)
fmt.Println(a, b, c, d, e)
fmt.Println(n, err)
// 在終端執(zhí)行后整吆,輸入 ABCDEFGabcdefg 回車
// 結(jié)果:
// ABC DEFG abc de
// 4 無(wú)效格式:x
}