美文网首页
io.Writer 解析

io.Writer 解析

作者: juniway | 来源:发表于2017-08-03 12:25 被阅读114次

    简介

    io.Writer 跟 io.Reader 一样,都是 Interface 类型,功能非常强大,在任何需要写入数据,处理数据流的地方,我们都应该尽可能使用这两个类型的对象。

    io.Writer 的原型:

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

    跟 io.Reader 类似,一个对象只要实现了 Write() 函数,这个对象就自动成为 Writer 类型。

    常见 Writer 类型

    (1)文件操作
    使用 os.Create() 创建文件时,会返回一个 os.File 对象,它是一个 struct,但是由于它实现了 Read() ,Write(),Closer() 等函数,因此它同时也是 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 语言中,string 类型是 immutable 的,因此它没有对应的 Writer,也就是说不存在 strings.NewWriter(s) 这种函数。最好的替代方式就是使用 bytes.Buffer,因为它既是一个 Reader 也是一个 Writer,我们既可以往里面写也可以往外读。我们可以通过 buf.String() 得到 string 类型的数据,也可以通过 buf.Bytes() 拿到 []byte 类型的数据。

    下面的例子展示了我们通过 bytes.NewBufferString(s) 函数,先在 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 语言进行 Web 开发时,http.ResponseWriter 是最基本的类型之一,它本身是一个 Interface 类,原型如下:

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

    可见,它只申明了需要实现三个函数,由于其要求了 Writer() 函数,包含了 Writer 的要求,因此,任何是符合 ResponserWriter 的类型必然是 Writer 类型。

    下面是一个http.ResponseWriter 最常见的使用场景和方法的:

    一、直接调用 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)
    }
    

    这种方式跟创建文件时,直接往文件对象中写入 []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 这个 interface 接口,作为所有 hash 函数的公共接口。它也是一个 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
    可以通过 bufio.NewWriter(r) 函数来把原 io.Writer 对象封装成一个 bufio.Writer 对象,从而进行 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()
    }
    

    相关文章

      网友评论

          本文标题:io.Writer 解析

          本文链接:https://www.haomeiwen.com/subject/vztplxtx.html