The io.Writer interface

The io.Writer interface, as shown in the following code, is just as simple as its reader counterpart:

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

The interface requires the implementation of a single method, Write(p []byte)(c int, e error), that copies data from the provided stream p and writes that data to a sink resource such as an in-memory structure, standard output, a file, a network connection, or any number of io.Writer implementations that come with the Go standard library. The Write method returns the number of bytes copied from p followed by an error value if any was encountered.

The following code snippet shows the implementation of the channelWriter type, a writer that decomposes and serializes its stream that is sent over a Go channel as consecutive bytes:

type channelWriter struct { 
   Channel chan byte 
} 
 
func NewChannelWriter() *channelWriter { 
   return &channelWriter{ 
         Channel: make(chan byte, 1024), 
   } 
} 
 
func (c *channelWriter) Write(p []byte) (int, error) { 
   if len(p) == 0 { 
         return 0, nil 
   } 
 
   go func() { 
         defer close(c.Channel) // when done 
         for _, b := range p { 
               c.Channel <- b 
         } 
   }() 
 
   return len(p), nil 
} 
 

golang.fyi/ch10/writer1.go

The Write method uses a goroutine to copy each byte, from p, and sends it across the c.Channel. Upon completion, the goroutine closes the channel so that consumers are notified when to stop consuming from the channel. As an implementation convention, writers should not modify slice p or hang on to it. When an error occurs, the writer should return the current number of bytes processed and an error.

Using the channelWriter type is simple. You can invoke the Write() method directly or, as is more common, use channelWriter with other IO primitives in the API. For instance, the following snippet uses the fmt.Fprint function to serialize the "Stream me!" string as a sequence of bytes over a channel using channelWriter:

func main() { 
   cw := NewChannelWriter() 
   go func() { 
         fmt.Fprint(cw, "Stream me!") 
   }() 
 
   for c := range cw.Channel { 
         fmt.Printf("%c
", c) 
   } 
} 

golang.fyi/ch10/writer1.go

In the previous snippet, the serialized bytes, queued in the channel, are consumed using a for…range statement as they are successively printed. The following snippet shows another example where the content of a file is serialized over a channel using the same channelWriter. In this implementation, an io.File value and io.Copy function are used to source the data instead of the fmt.Fprint function:

func main() { 
   cw := NewChannelWriter() 
   file, err := os.Open("./writer2.go") 
   if err != nil { 
         fmt.Println("Error reading file:", err) 
         os.Exit(1) 
   } 
   _, err = io.Copy(cw, file) 
   if err != nil { 
         fmt.Println("Error copying:", err) 
         os.Exit(1) 
   } 
 
   // consume channel 
   for c := range cw.Channel { 
         fmt.Printf("%c
", c) 
   } 
} 

golang.fyi/ch10/writer2.go.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.93.0