天天看點

一文搞懂Go語言标準庫,fmt

fmt 包含有格式化I/O函數,類似于C語言的 printf 和 scanf。主要分為向外輸出内容和擷取輸入内容兩大部分。

輸出

Print

Print 系列函數會将内容輸出到系統的标準輸出。

  • Print 函數直接輸出内容。
  • Println 函數會在輸出内容的結尾添加一個換行符。
  • Printf 函數支援格式化輸出字元串。
func Print(a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)
func Printf(format string, a ...interface{}) (n int, err error)      

舉例說明:

func main() {
    fmt.Print("直接輸出内容", "\n") // \n :手動換行
    fmt.Println("自動加換行")
    name := "微客鳥窩"
    fmt.Printf("我是:%s\n", name)
}      

運作結果:

直接輸出内容
自動加換行
我是:微客鳥窩      

Fprint

Fprint 系列函數會将内容輸出到一個 io.Writer 接口類型的變量 w 中,通常會用這個函數往檔案中寫内容。

func Fprint(w io.Writer, a ...interface{}) (n int, err error)
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)      

舉例說明:

// 向标準輸出寫入内容
fmt.Fprintln(os.Stdout, "向标準輸出寫入内容")
fileObj, err := os.OpenFile("./xxx.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
    fmt.Println("打開檔案出錯,err:", err)
    return
}
name := "微客鳥窩"
// 向打開的檔案句柄中寫入内容
fmt.Fprintf(fileObj, "往檔案中寫入内容:%s", name)      

注意,隻要滿足io.Writer接口的類型都支援寫入。

Sprint

Sprint 系列函數會把傳入的資料生成并傳回一個字元串。

func Sprint(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
func Sprintln(a ...interface{}) string      

舉例說明:

func main() {
      s1 := fmt.Sprint("微客鳥窩")
      name := "微客鳥窩"
      age := 18
      s2 := fmt.Sprintf("name:%s,age:%d", name, age)
      s3 := fmt.Sprintln("微客鳥窩")
      s4 := fmt.Sprintln("微客鳥窩")
      fmt.Println(s1, s2, s3, s4)
}      

運作結果:

微客鳥窩 name:微客鳥窩,age:18      

Errorf

Errorf 函數根據 format 參數生成格式化字元串,并傳回一個包含該字元串的錯誤。

func Errorf(format string, a ...interface{}) error      

我們通常使用這種方式來自定義錯誤類型:

func main() {
    err := fmt.Errorf("錯誤碼:%d", 404)
    fmt.Println("發生一個錯誤,", err)
}      

運作結果:

發生一個錯誤, 錯誤碼:404      

格式化占位符

​*printf​

​ 系列函數都支援format格式化參數。

通用占位符

占位符 說明 示例
%v 值的預設格式表示

fmt.Printf("%v\n", 100)}

//100

%+v 類似%v,但輸出結構體時會添加字段名

o := struct{ name string }{"微客"}

fmt.Printf("%+v\n", o)}}

//{name:微客}

%#v 值的Go文法表示

o := struct{ name string }{"微客"}

fmt.Printf("%#v\n", o) }

//struct { name string }{name:"微客"}

%T 列印值的類型

o := struct{ name string }{"微客"}

fmt.Printf("%T\n", o) }

//struct { name string }

%% 百分号

fmt.Printf("100%%\n") }

//100%

布爾型

占位符 說明
%t true或false

整型

占位符 說明 示例
%b 表示為二進制

fmt.Printf("%b\n", 65)

//1000001

%c 該值對應的unicode碼值

fmt.Printf("%c\n", 65)

//A

%d 表示為十進制

fmt.Printf("%d\n", 65)

//65

%o 表示為八進制

fmt.Printf("%o\n", 65)

//101

%x 表示為十六進制,使用a-f

fmt.Printf("%x\n", 65)

//41

%X 表示為十六進制,使用A-F

fmt.Printf("%X\n", 65)

//41

%U 表示為Unicode格式:U+1234,等價于”U+%04X”
%q

該值對應的單引号括起來的go文法字元字面值

必要時會采用安全的轉義表示

fmt.Printf("%q\n", 65)

//'A'

浮點數與複數

占位符 說明 示例
%b 無小數部分、二進制指數的科學計數法,如-123456p-78

fmt.Printf("%b\n", 12.34)

//6946802425218990p-49

%e 科學計數法,如-1234.456e+78

fmt.Printf("%e\n", f)

//1.234000e+01

%E 科學計數法,如-1234.456E+78

fmt.Printf("%E\n", f)

//1.234000E+01

%f 有小數部分但無指數部分,如123.456

fmt.Printf("%f\n", f)

//12.340000

%F 等價于%f

fmt.Printf("%F\n", 12.34)

//12.340000

%g 根據實際情況采用%e或%f格式(以獲得更簡潔、準确的輸出)

fmt.Printf("%g\n", f)

//12.34

%G 根據實際情況采用%E或%F格式(以獲得更簡潔、準确的輸出)

fmt.Printf("%G\n", f)

//12.34

字元串和[]byte

占位符 說明 示例
%s 直接輸出字元串或者[]byte

fmt.Printf("%s\n", "微客")

//微客

%q 該值對應的雙引号括起來的go文法字元串字面值,必要時會采用安全的轉義表示

fmt.Printf("%q\n", "微客")

//"微客"

%x 每個位元組用兩字元十六進制數表示(使用a-f

fmt.Printf("%x\n", "微客")

//e5beaee5aea2

%X 每個位元組用兩字元十六進制數表示(使用A-F)

fmt.Printf("%X\n", "微客")

//E5BEAEE5AEA2

指針

占位符 說明
%p 表示為十六進制,并加上前導的0x

寬度辨別符

占位符 說明
%f 預設寬度,預設精度
%9f 寬度9,預設精度
%.2f 預設寬度,精度2
%9.2f 寬度9,精度2
%9.f 寬度9,精度0

其他falg

占位符 說明
’+’ 總是輸出數值的正負号;對%q(%+q)會生成全部是ASCII字元的輸出(通過轉義)
’ ‘ 對數值,正數前加空格而負數前加負号;對字元串采用%x或%X時(% x或% X)會給各列印的位元組之間加空格
’-’ 在輸出右邊填充空白而不是預設的左邊(即從預設的右對齊切換為左對齊)
’#’ 八進制數前加0(%#o),十六進制數前加0x(%#x)或0X(%#X),指針去掉前面的0x(%#p)對%q(%#q),對%U(%#U)會輸出空格和單引号括起來的go字面值
‘0’ 使用0而不是空格填充,對于數值類型會把填充的0放在正負号後面

輸入

fmt 包下有 fmt.Scan、fmt.Scanf、fmt.Scanln 三個函數,可以在程式運作過程中從标準輸入擷取使用者的輸入。

fmt.Scan

func Scan(a ...interface{}) (n int, err error)      
  • Scan 從标準輸入掃描文本,讀取由空白符分隔的值儲存到傳遞給本函數的參數中,換行符視為空白符。
  • 本函數傳回成功掃描的資料個數和遇到的任何錯誤。
  • 如果讀取的資料個數比提供的參數少,會傳回一個錯誤報告原因。

舉例說明:

func main() {
    var (
        name    string
        age     int
    )
    fmt.Scan(&name, &age)
    fmt.Printf("掃描結果 name:%s age:%d \n", name, age)
}      

将上面的代碼編譯後在終端執行,在終端依次輸入微客鳥窩、18使用空格分隔。

$ ./scan_demo      

fmt.Scanf

func Scanf(format string, a ...interface{}) (n int, err error)      
  • Scanf從标準輸入掃描文本,根據 format 參數指定的格式去讀取由空白符分隔的值儲存到傳遞給本函數的參數中。
  • 本函數傳回成功掃描的資料個數和遇到的任何錯誤。

舉例說明:

func main() {
    var (
        name    string
        age     int
    )
    fmt.Scanf("1:%s 2:%d", &name, &age)
    fmt.Printf("掃描結果 name:%s age:%d \n", name, age)
}      

将上面的代碼編譯後在終端執行,在終端按照指定的格式依次輸入微客鳥窩、18。

$ ./scan_demo      

fmt.Scanln

func Scanln(a ...interface{}) (n int, err error)      
  • Scanln 類似 Scan,它在遇到換行時才停止掃描。最後一個資料後面必須有換行或者到達結束位置。
  • 本函數傳回成功掃描的資料個數和遇到的任何錯誤。

舉例說明:

func main() {
    var (
        name    string
        age     int
    )
    fmt.Scanln(&name, &age)
    fmt.Printf("掃描結果 name:%s age:%d \n", name, age)
}      

将上面的代碼編譯後在終端執行,在終端依次輸入微客鳥窩、18使用空格分隔。

$ ./scan_demo      

bufio.NewReader

有時候我們想完整擷取輸入的内容,而輸入的内容可能包含空格,這種情況下可以使用 bufio 包來實作。

func bufioDemo() {
    reader := bufio.NewReader(os.Stdin) // 從标準輸入生成讀對象
    fmt.Print("請輸入内容:")
    text, _ := reader.ReadString('\n') // 讀到換行
    text = strings.TrimSpace(text)
    fmt.Printf("%#v\n", text)
}      

Fscan系列

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)      

Sscan系列

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)
``