Golang學習 - fmt 包

------------------------------------------------------------

// Print 將參數列表 a 中的各個參數轉換爲字符串並寫入到標準輸出中。
// 非字符串參數之間會添加空格,返回寫入的字節數。
func Print(a ...interface{}) (n int, err error)

// Println 功能相似 Print,只不過最後會添加一個換行符。
// 全部參數之間會添加空格,返回寫入的字節數。
func Println(a ...interface{}) (n int, err error)

// Printf 將參數列表 a 填寫到格式字符串 format 的佔位符中。
// 填寫後的結果寫入到標準輸出中,返回寫入的字節數。
func Printf(format string, a ...interface{}) (n int, err error)

------------------------------

// 功能同上面三個函數,只不過將轉換結果寫入到 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)

------------------------------

// 功能同上面三個函數,只不過將轉換結果以字符串形式返回。
func Sprint(a ...interface{}) string
func Sprintln(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string

------------------------------

// 功能同 Sprintf,只不過結果字符串被包裝成了 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%
	// 數值 160 超出範圍(100)
}

func percent(i ...int) error {
	for _, n := range i {
		if n > 100 {
			return fmt.Errorf("數值 %d 超出範圍(100)", n)
		}
		fmt.Print(n, "%\n")
	}
	return nil
}

------------------------------------------------------------

// Formatter 由自定義類型實現,用於實現該類型的自定義格式化過程。
// 當格式化器須要格式化該類型的變量時,會調用其 Format 方法。
type Formatter interface {
	// f 用於獲取佔位符的旗標、寬度、精度等信息,也用於輸出格式化的結果
	// c 是佔位符中的動詞
	Format(f State, c rune)
}

// 由格式化器(Print 之類的函數)實現,用於給自定義格式化過程提供信息
type State interface {
	// Formatter 經過 Write 方法將格式化結果寫入格式化器中,以便輸出。
	Write(b []byte) (ret int, err error)
	// Formatter 經過 Width 方法獲取佔位符中的寬度信息及其是否被設置。
	Width() (wid int, ok bool)
	// Formatter 經過 Precision 方法獲取佔位符中的精度信息及其是否被設置。
	Precision() (prec int, ok bool)
	// Formatter 經過 Flag 方法獲取佔位符中的旗標[+- 0#]是否被設置。
	Flag(c int) bool
}

// Stringer 由自定義類型實現,用於實現該類型的自定義格式化過程。
// 當格式化器須要輸出該類型的字符串格式時就會調用其 String 方法。
type Stringer interface {
	String() string
}

// Stringer 由自定義類型實現,用於實現該類型的自定義格式化過程。
// 當格式化器須要輸出該類型的 Go 語法字符串(%#v)時就會調用其 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("旗標:[")
		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 函數,則必須本身處理全部格式,包括 %#v
		if c == 'v' && f.Flag('#') {
			write(u.GoString())
		} else {
			write(u.String())
		}
	default: // 若是使用 Format 函數,則必須本身處理默認輸出
		write("無效格式:" + string(c))
	}
}

func main() {
	u := Ustr("Hello World!")
	// "-" 標記和 "0" 標記不能同時存在
	fmt.Printf("%-+ 0#8.5m\n", u) // 旗標:[+- #] | 寬度:8 | 精度:5
	fmt.Printf("%+ 0#8.5M\n", u)  // 旗標:[+ 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)         // 無效格式:d
}

------------------------------------------------------------

// Scan 從標準輸入中讀取數據,並將數據用空白分割並解析後存入 a 提供
// 的變量中(換行符會被看成空白處理),變量必須以指針傳入。
// 當讀到 EOF 或全部變量都填寫完畢則中止掃描。
// 返回成功解析的參數數量。
func Scan(a ...interface{}) (n int, err error)

// Scanln 和 Scan 相似,只不過遇到換行符就中止掃描。
func Scanln(a ...interface{}) (n int, err error)

// Scanf 從標準輸入中讀取數據,並根據格式字符串 format 對數據進行解析,
// 將解析結果存入參數 a 所提供的變量中,變量必須以指針傳入。
// 輸入端的換行符必須和 format 中的換行符相對應(若是格式字符串中有換行
// 符,則輸入端必須輸入相應的換行符)。
// 佔位符 %c 老是匹配下一個字符,包括空白,好比空格符、製表符、換行符。
// 返回成功解析的參數數量。
func Scanf(format string, a ...interface{}) (n int, err error)

// 功能同上面三個函數,只不過從 r 中讀取數據。
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)

// 功能同上面三個函數,只不過從 str 中讀取數據。
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)

------------------------------

// 示例

// 對於 Scan 而言,回車視爲空白
func main() {
	a, b, c := "", 0, false
	fmt.Scan(&a, &b, &c)
	fmt.Println(a, b, c)
	// 在終端執行後,輸入 abc 1 回車 true 回車
	// 結果 abc 1 true
}

// 對於 Scanln 而言,回車結束掃描
func main() {
	a, b, c := "", 0, false
	fmt.Scanln(&a, &b, &c)
	fmt.Println(a, b, c)
	// 在終端執行後,輸入 abc 1 true 回車
	// 結果 abc 1 true
}

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

------------------------------------------------------------

// Scanner 由自定義類型實現,用於實現該類型的自定義掃描過程。
// 當掃描器須要解析該類型的數據時,會調用其 Scan 方法。
type Scanner interface {
	// state 用於獲取佔位符中的寬度信息,也用於從掃描器中讀取數據進行解析。
	// verb 是佔位符中的動詞
	Scan(state ScanState, verb rune) error
}

// 由掃描器(Scan 之類的函數)實現,用於給自定義掃描過程提供數據和信息。
type ScanState interface {
	// ReadRune 從掃描器中讀取一個字符,若是用在 Scanln 類的掃描器中,
	// 則該方法會在讀到第一個換行符以後或讀到指定寬度以後返回 EOF。
	// 返回「讀取的字符」和「字符編碼所佔用的字節數」
	ReadRune() (r rune, size int, err error)
	// UnreadRune 撤消最後一次的 ReadRune 操做,
	// 使下次的 ReadRune 操做獲得與前一次 ReadRune 相同的結果。
	UnreadRune() error
	// SkipSpace 爲 Scan 方法提供跳過開頭空白的能力。
	// 根據掃描器的不一樣(Scan 或 Scanln)決定是否跳過換行符。
	SkipSpace()
	// Token 用於從掃描器中讀取符合要求的字符串,
	// Token 從掃描器中讀取連續的符合 f(c) 的字符 c,準備解析。
	// 若是 f 爲 nil,則使用 !unicode.IsSpace(c) 代替 f(c)。
	// skipSpace:是否跳過開頭的連續空白。返回讀取到的數據。
	// 注意:token 指向共享的數據,下次的 Token 操做可能會覆蓋本次的結果。
	Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
	// Width 返回佔位符中的寬度值以及寬度值是否被設置
	Width() (wid int, ok bool)
	// 由於上面實現了 ReadRune 方法,因此 Read 方法永遠不該該被調用。
	// 一個好的 ScanState 應該讓 Read 直接返回相應的錯誤信息。
	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("無效格式:%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)
	// 在終端執行後,輸入 ABCDEFGabcdefg 回車
	// 結果:
	// ABC DEFG abc de
	// 4 無效格式:x
}

------------------------------------------------------------



相關文章
相關標籤/搜索