iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 13
1

前言

一般來說,程序運行的流程會是:從檔案或是使用者輸入(Input)資料經過程序的算法邏輯處理過,輸出相對應的結果。一般來說,程序語言都會提供I/O包供開發者直接調用,Go語言也不例外。

Go語言提供了幾個I/O的包可以直接調用:

  • io: 為I/O primitives,提供了基本接口
  • io/ioutil: 在io包的基礎上封裝了一些更實用的I/O函數
  • fmt: 實現格式化I/O,類似 C 語言中的 printf 和 scanf
  • bufio: 實現帶緩衝的I/O

讀取文件

一般而言,讀取文件的常用方法有四種

  1. File的Read()
  2. buifio.Read()
  3. io/ioutil.ReadAll()
  4. io/ioutil.ReadFile()

簡單結論,追求性能就用bufio,方便調用就呼叫ioutil,不建議使用普通的Read.

io

io 包为 I/O 原语提供了基本的接口。它主要包装了这些原语的已有实现。

由于这些被接口包装的I/O原语是由不同的低级操作实现,因此,在另有声明之前不该假定它们的并行执行是安全的。

在 io 包中最重要的是两个接口:Reader 和 Writer 接口。本章所提到的各种 IO 包,都跟这两个接口有关,也就是说,只要满足这两个接口,它就可以使用 IO 包的功能。

reader接口

Reader 接口的定義如下:

type Reader interface {
    Read(p []byte) (n int, err error)
}

官方文檔中關於該接口方法的說明:

Read 將 len(p) 個字節讀取到 p 中。它返回讀取的字節數 n(0 <= n <= len(p)) 以及任何遇到的錯誤。即使 Read 返回的 n < len(p),它也會在調用過程中占用 len(p) 個字節作為暫存空間。若可讀取的數據不到 len(p) 個字節,Read 會返回可用數據,而不是等待更多數據。
當 Read 在成功讀取 n > 0 個字節後遇到一個錯誤或 EOF (end-of-file),它會返回讀取的字節數。它可能會同時在本次的調用中返回一個non-nil錯誤,或在下一次的調用中返回這個錯誤(且 n 為 0)。 一般情況下, Reader會返回一個非0字節數n, 若 n = len(p) 個字節從輸入源的結尾處由 Read 返回,Read可能返回 err == EOF 或者 err == nil。並且之後的 Read() 都應該返回 (n:0, err:EOF)。
調用者在考慮錯誤之前應當首先處理返回的數據。這樣做可以正確地處理在讀取一些字節後產生的 I/O 錯誤,同時允許EOF的出現。

writer接口

Writer 接口的定義如下:

type Writer interface {
    Write(p []byte) (n int, err error)
}

官方文檔中關於該接口方法的說明:

Write 將 len(p) 個字節從 p 中寫入到基本數據流中。它返回從 p 中被寫入的字節數 n(0 <= n <= len(p))以及任何遇到的引起寫入提前停止的錯誤。若 Write 返回的 n < len(p),它就必須返回一個 非nil 的錯誤。

io/ioutil

fmt

import "fmt"

软件包fmt实现了格式化的I / O,其功能类似于C的printf和scanf。格式'动词'来自C,但更简单。

Printing
已有示例代码:

舉例

type Car struct{
    Name string
}

car := Car(Rambo)

通用

占位符 說明 範例 輸出
%v 相應參數的默認格式
%+v 類似%v,輸出struct時會添加屬性作為前綴 Printf("%v",car ) {Rambo}
%#v 相應參數的Go語法表示 Printf("%+v",car ) {Name:Rambo}
%T 相應參數之資料類型的Go語法表示 Printf("%T",person ) main.Car
%% 輸出百分比符號 Printf("%%") %

布哥值

占位符 說明 範例 輸出
%t true或false Print("%t",true) true

整數

占位符 說明 範例 輸出
%b 二進制表示 Printf("%b",4 100
%c 該值對應的unicode碼 Printf("%c",0x4E2d
%d 十進制表示 Printf("%d",0x10) 16
%o 八進制表示 Printf("%o",10) 12
%q 轉釋為帶有單引號的字符串unicode碼 Printf("%q",0x4E2d) '中'
%x 十六進制表示,字母為小寫a-f Printf("%x",13) d
%X 十六進制表示,字母為大寫A-F Printf("%X",13) D
%U 表示為Unicode格式 Printf("%U",0x4E2d) U+4E2D

浮點數和複數

占位符 說明 範例 輸出
%b 無小數部分、指數為二的冪的科學計數法,與strconv.FormatFloat的'b'轉換格式一致。 Printf("%b",10.20) 5742089524897382p-49
%e 科學計數法,如-1234.456e+78 Printf("%e",10.20) 1.020000e+01
%E 科學計數法,如-1234.456E+78 Printf("%E",10.20) 1.020000E+01
%f 有小數部分但無指數部分,如123.456 Printf("%f",10.20) 10.200000
%g 根據實際情況采用%e或%f格式(以獲得更簡潔、準確的輸出) Printf("%g",10.20) 10.2
%G 根據實際情況采用%E或%F格式(以獲得更簡潔、準確的輸出) Printf("%G",10.20) (10.2+2i)

字符串和[]byte

占位符 說明 範例 輸出
%s 輸出字符串表示(string類型或[]byte) Printf("%s",[]byte("Go語言")) Go語言
%q 雙引號圍繞的字符串,由Go語法安全的轉譯 Printf("%q","Go語言") "Go語言"
%x 十六進制,小寫字母,每字節兩個字符 Printf("%x","golang") 676f6c616e67
%X 十六進制,大寫字母,每字節兩個字符 Printf("%X","golang") 676F6C616E67

指針

占位符 說明 範例 輸出
%P 十六進制表示,前綴 0x Printf("%p",&car) 0xc042214aa

其他

占位符 說明 範例 輸出
+ 總是輸出數值的正負號;對%q(%+q)會生成全部是ASCII字符的輸出(通過轉義) Printf("%+q","中文") "\u4e2d\u6587"
- 在輸出右邊填充空白而不是默認的左邊(即從默認的右對齊切換為左對齊);
# 切換格式:八進制數前加0(%#o) Printf("%#0",46)
_ 十六進制數前加0x(%#x)或0X(%#X) Printf("%#x",46) 0x2e
_ 指針去掉前面的0x(%#p);) fmt.Printf("%#p",&person) c0420441b0
_ 對%q(%#q),如果strconv.CanBackquote返回真會輸出反引號括起來的未轉義字符串; Printf("%#q",'中') '中'
_ 對%U(%#U),如果字符是可打印的,會在輸出Unicode格式、空格、單引號括起來的go字面值; Printf("%#U",'中') U+4E2D '中'
' ' (空格)為數值中省略的正負號流出空白(% d) Printf("% d",16) 16
_ 以十六進制(% x,% X)打印字符串或切片時,在字節之間用空格隔開 Printf("% x","abc") 61 62 63
0 使用0而不是空格填充,對於數值類型會把填充的0放在正負號後面

函數

Print

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

Println

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

Printf

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

Fprintf

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

Sprintf

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

Errorf

// 功能同 Sprintf,只不過結果字符串被包裝成了 error 類型。
func Errorf(format string, a ...interface{}) error

bufio


上一篇
Day12 網路通訊協定
下一篇
Day14 First-class Object
系列文
Golang入門到進階實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言