io.Writer 解析

簡(jiǎn)介

io.Writer 跟 io.Reader 一樣哆键,都是 Interface 類型,功能非常強(qiáng)大闪盔,在任何需要寫入數(shù)據(jù)噩峦,處理數(shù)據(jù)流的地方识补,我們都應(yīng)該盡可能使用這兩個(gè)類型的對(duì)象。

io.Writer 的原型:

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

跟 io.Reader 類似祝辣,一個(gè)對(duì)象只要實(shí)現(xiàn)了 Write() 函數(shù)蝙斜,這個(gè)對(duì)象就自動(dòng)成為 Writer 類型澎胡。

常見(jiàn) Writer 類型

(1)文件操作
使用 os.Create() 創(chuàng)建文件時(shí),會(huì)返回一個(gè) os.File 對(duì)象稚伍,它是一個(gè) struct个曙,但是由于它實(shí)現(xiàn)了 Read() ,Write()呼寸,Closer() 等函數(shù)对雪,因此它同時(shí)也是 Reader, Writer, Closer 等類型慌植。

type File struct {
    *file // os specific
}

func (f *File) Write(b []byte) (n int, err error) {
    if err := f.checkValid("write"); err != nil {
        return 0, err
    }
    n, e := f.write(b)
    if n < 0 {
        n = 0
    }
    if n != len(b) {
        err = io.ErrShortWrite
    }

    epipecheck(f, e)

    if e != nil {
        err = &PathError{"write", f.name, e}
    }
    return n, err
}

(2)bytes.Buffer
在 Go 語(yǔ)言中,string 類型是 immutable 的丈钙,因此它沒(méi)有對(duì)應(yīng)的 Writer,也就是說(shuō)不存在 strings.NewWriter(s) 這種函數(shù)劫笙。最好的替代方式就是使用 bytes.Buffer填大,因?yàn)樗仁且粋€(gè) Reader 也是一個(gè) Writer允华,我們既可以往里面寫也可以往外讀寥掐。我們可以通過(guò) buf.String() 得到 string 類型的數(shù)據(jù),也可以通過(guò) buf.Bytes() 拿到 []byte 類型的數(shù)據(jù)百炬。

下面的例子展示了我們通過(guò) bytes.NewBufferString(s) 函數(shù)剖踊,先在 buffer 中初始化一段 string,然后往里面 append 另外一段 string歇攻。

s := "Hello"
buf := bytes.NewBufferString(s)
s2 := "to be appended"
buf.WriteString(s2)   // 或者 fmt.Fprint(buf, s2)
fmt.Println("Final string:", buf.String())

(3)http.ResponseWriter
在使用 Go 語(yǔ)言進(jìn)行 Web 開(kāi)發(fā)時(shí)掉伏,http.ResponseWriter 是最基本的類型之一澳窑,它本身是一個(gè) Interface 類摊聋,原型如下:

type ResponseWriter interface {
    Header() Header
    Write([]byte) (int, error)
    WriteHeader(int)
}

可見(jiàn)麻裁,它只申明了需要實(shí)現(xiàn)三個(gè)函數(shù)煎源,由于其要求了 Writer() 函數(shù)手销,包含了 Writer 的要求,因此诈悍,任何是符合 ResponserWriter 的類型必然是 Writer 類型侥钳。

下面是一個(gè)http.ResponseWriter 最常見(jiàn)的使用場(chǎng)景和方法的:

一舷夺、直接調(diào)用 Write() 寫入一串 []byte

func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/plain") 
    w.Write([]byte("Hello World"))
    return
}

func main() {
    http.HandleFunc("/", helloHandler)
    http.ListenAndServe(":8080", nil)
}

這種方式跟創(chuàng)建文件時(shí)冕房,直接往文件對(duì)象中寫入 []byte 是一樣的:

func main() {
    f, _:= os.Create("test.txt")
    if _, err = f.Write([]byte("Hello world")); err != nil {
            log.Fatal(err)
    }
    f.Close()
}

二耙册、或者 使用 io.WriteStirng() 或者 fmt.Fprintf() 往 Writer 中寫入 string

func helloHandler(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "Hello world!")
        fmt.Fprintf(w, "Hello, World!")
}
func main() {
    http.HandleFunc("/", helloHandler)
    http.ListenAndServe(":8080", nil)
}

(4) hash.Hash
hash 包中申明了 Hash 這個(gè) interface 接口详拙,作為所有 hash 函數(shù)的公共接口饶辙。它也是一個(gè) Writer弃揽,原型如下:

type Hash interface {
    // Write (via the embedded io.Writer interface) adds more data to the running hash.
    // It never returns an error.
    io.Writer

    // Sum appends the current hash to b and returns the resulting slice.
    // It does not change the underlying hash state.
    Sum(b []byte) []byte

    // Reset resets the Hash to its initial state.
    Reset()

    // Size returns the number of bytes Sum will return.
    Size() int

    // BlockSize returns the hash's underlying block size.
    // The Write method must be able to accept any amount
    // of data, but it may operate more efficiently if all writes
    // are a multiple of the block size.
    BlockSize() int
}

使用方式

import (
    "crypto/sha1"
)

func main() {
    passwordHash := sha1.New()
    io.WriteString(passwordHash, combination) // 或者直接 passwordHash.Write(combination)
    fmt.Printf("Password Hash : %x \n", passwordHash.Sum(nil))
}

(5) bufio
可以通過(guò) bufio.NewWriter(r) 函數(shù)來(lái)把原 io.Writer 對(duì)象封裝成一個(gè) bufio.Writer 對(duì)象脯爪,從而進(jìn)行 buffered 讀寫。

package main

import (
    "bufio"
    "os"
)

func main() {
    f, _ := os.Create("file.txt")
    w := bufio.NewWriter(f) // Create a new writer.
    w.WriteString("ABC")  // Write a string to the file.
    w.Flush()
}

(6) gzip 壓縮

package main

import (
    "bufio"
    "compress/gzip"
    "fmt"
    "io/ioutil"
    "os"
    "strings"
)

func main() {
    // Open file on disk.
    name := "file.txt"
    f, _ := os.Open("C:\\programs\\" + name)

    // Create a Reader and use ReadAll to get all the bytes from the file.
    reader := bufio.NewReader(f)
    content, _ := ioutil.ReadAll(reader)

    // Replace txt extension with gz extension.
    name = strings.Replace(name, ".txt", ".gz", -1)

    f, _ = os.Create("C:\\programs\\" + name)

    w := gzip.NewWriter(f)
    w.Write(content)
    w.Close()
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末矿微,一起剝皮案震驚了整個(gè)濱河市痕慢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涌矢,老刑警劉巖掖举,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異娜庇,居然都是意外死亡塔次,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門名秀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)励负,“玉大人耗跛,你說(shuō)我怎么就攤上這事「崂” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵申鱼,是天一觀的道長(zhǎng)捐友。 經(jīng)常有香客問(wèn)我科吭,道長(zhǎng)变隔,這世上最難降的妖魔是什么猖闪? 我笑而不...
    開(kāi)封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任吵护,我火速辦了婚禮譬圣,結(jié)果婚禮上屯蹦,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好空郊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著谐腰,像睡著了一般砸西。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天潘鲫,我揣著相機(jī)與錄音熄攘,去河邊找鬼。 笑死吩案,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播壳快,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼七婴!你這毒婦竟也來(lái)了杭棵?” 一聲冷哼從身側(cè)響起滓侍,我...
    開(kāi)封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泣栈,沒(méi)想到半個(gè)月后疼进,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體诞外,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡啥纸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年穗酥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呜师,到底是詐尸還是另有隱情祈争,我是刑警寧澤墨吓,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站瞬痘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜娶视,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望致开。 院中可真熱鬧,春花似錦飒货、人聲如沸哲银。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春虏杰,著一層夾襖步出監(jiān)牢的瞬間纺阔,已是汗流浹背囤捻。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工醋拧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慷嗜,地道東北人淀弹。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像庆械,于是被迫代替她去往敵國(guó)和親薇溃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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