簡(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()
}