Go Language Practical Notes (19) | Go Writer and Reader

Source: Internet
Author: User
Tags log log
This is a creation in Article, where the information may have evolved or changed.

"Go language Combat" reading notes, not to be continued, welcome to sweep code attention flysnow_org to the public or website http://www.flysnow.org/, the first time to see follow-up notes. If you feel helpful, share it with your friends and thank you for your support.

Input and output

The Go Writer and reader interfaces are designed to follow UNIX input and output, and the output of one program can be an input to another program. They are simple and pure, so they can be very easy to write program code, but also through the concept of combinatorial, let our program do more things.

For example, in the previous go log log http://www.flysnow.org/2017/05/06/go-in-action-go-log.html, we introduced the UNIX three input and output input modes, They have a specific implementation in their corresponding go language.

12345
var (Stdin  = NewFile (uintptr"/dev/stdin") Stdout = NewFile (uintptr"/dev/stdout" ) Stderr = NewFile (uintptr"/dev/stderr"))

The input and output of these three standards is one *File , and *File exactly is the type of the io.Writer io.Reader two interfaces, so they have both input and output functions, can read from the inside of the data, but also to write data inside.

The Go standard library IO package is also based on the UNIX input and output concept, most of the interfaces are extended io.Writer and io.Reader , most of the types are also selected to implement io.Writer and io.Reader the two interfaces, and then the data input and output, abstract as a stream of read and write, So as long as the two interfaces are implemented, both the read and write functions of the stream can be used.

io.Writerand io.Reader two interfaces of the high abstraction, let us no longer face the specific business, we only focus on, is read or write, as long as we define the method function can receive the two interfaces as parameters, then we can do the stream read and write, without care about how the reading, where to write, this is the benefit of interface programming.

Reader and writer interfaces

These two highly abstract interfaces, with only one method, also embody the simplicity of the Go interface design and only do a thing.

 123456789101112 
 // Writer is the interface that wraps the basic Write method.  // //Write writes Len (p) bytes from p to the underlying data stream.  //It returns the number of bytes written from p (0 <= n <= len (p))  //and any error encountered this caused the write to stop early.  //Write must return a non-nil error if it returns n < Len (p).  //Write must not modify the slice data, even temporarily.  // //implementations must not retain p.  type  Writer interface  {Write (p []byte ) (n int , err Error)} 

This is Wirter the definition of the interface, it has only one Write method, accepts a byte slice, returns two values, n indicates the number of bytes written, and err indicates the error that occurred while writing.

From its documentation annotations, this approach is prescriptive, and if we want to implement an interface, we need to io.Writer follow these rules.

    1. The Write method writes Len (p) bytes of data to the underlying data stream, which is derived from the slice p
    2. Returns the number of bytes written n,0 <= n <= len (p)
    3. If N<len (p), you must return some non-nil err
    4. Return non-nil err if there is a problem in the middle
    5. The Write method must never modify the slice p and the data inside

These implementations io.Writer of the interface rules, all of which implement the type of the interface to abide by, otherwise it may lead to inexplicable problems.

12345678910111213141516171819202122232425262728293031
//Reader is the interface that wraps the basic Read method.////Read reads up to Len (p) bytes into p. It returns the number of bytes//Read (0 <= n <= len (p)) and any error encountered. Even if Read///returns n < Len (p), it may use any of the p as scratch space during the call.//If Some data is available and not Len (p) bytes, Read conventionally//returns what's available instead of waiting for more.////When Read encounters a error or End-of-file condition after//successfully reading n > 0 bytes, it returns the number of//bytes read. It may return the (Non-nil) error from the same call//or return the error (and n = = 0) from a subsequent call.//An instance of the this general case was that a Reader returning//A non-zero number of bytes at the end of the input stream may//return either err = = EOF or err = nil. The next Read should//Return 0, EOF.////callers should always process the N > 0 bytes returned before//Considering the error err. Doing so correctly handles I/O errors//That happen after reading some bytes and also both of the//Allowed EOF behaviors.////implementations of Read is discouraged from returning a//Zero byte count with a nil error, except when Len (p) = = 0.//callers should treat a return of 0 and nil as indicating that//Nothing happened, in particular it does not indicate EOF.////implementations must not retain p.typeReaderInterface{Read (P []byte) (nint, err Error)}

This is the io.Reader interface definition, and there is only one read method, this method accepts a byte slice, and returns two values, one is the number of bytes read, and the other is the ERR error.

From its annotated document, there io.Reader are more rules for interfaces.

    1. Read reads a maximum of Len (p) bytes of data and saves it to p.
    2. Returns the number of bytes read and any error messages that occurred
    3. N to meet 0 <= N <= len (p)
    4. N<len (p), indicates that the data read is not sufficient to fill p, and the method returns immediately instead of waiting for more data
    5. Error encountered during reading, the number of bytes read n and corresponding error is returned err
    6. At the end of the underlying input stream, the method returns n>0 bytes, but err may be EOF or nil
    7. In the 6th (above) case, when the Read method is called again, it will definitely return 0,eof
    8. When calling the Read method, if n>0, processing the read-in data first, and then processing the error err,eof to do the same
    9. The Read method does not encourage the return of n=0 and Err=nil cases,

The rule is Write a little bit more than the interface, but it is also better understood, note 8th, even if we encountered errors while reading, but also should deal with the data already read, because these have read the data is correct, if not processed lost, the reading of the data is not complete.

"Go language Combat" reading notes, not to be continued, welcome to sweep code attention flysnow_org to the public or website http://www.flysnow.org/, the first time to see follow-up notes. If you feel helpful, share it with your friends and thank you for your support.

Example

After understanding the two interfaces, we can try to use them, and now look at an example.

 1234567891011 
 func  main   ()   {//define 0 value buffer type variable b  var  b bytes. Buffer//use the Write method to write the string  b.write ([]byte  (  "Hello" )) //this is to stitch a string into buffer  FMT. Fprint (&b,, " http://www.flysnow.org ") //print the contents of buffer to the terminal console  b.writeto (OS. Stdout)} 

This example is the concatenation of strings into Buffer , and then output to the console, this example is very simple, but the use of the stream read and write, bytes.Buffer is a variable byte type, can make it easy for us to operate on the byte, such as read and write, append and so on. bytes.Bufferimplementation io.Writer and io.Reader interface, so I can easily read and write operations, instead of focusing on specific implementations.

b.Write([]byte("你好"))Implemented to write a string, we convert the string to a byte slice, and then invoke the Write method to write, which is implemented bytes.Buffer to implement io.Writer the interface, a method that can help us write to the data stream.

12345
func (b *buffer) Write (p []byte)  int, err error)  {B.lastread = Opinvalidm: = B.grow (len(p))returncopynil}

The above bytes.Buffer is io.Writer the way to implement the interface, and finally we see that we write the slices will be copied into the b.buf , where the b.buf[m:] copy is actually added meaning, will not overwrite the existing data.

From the implementation point of view, we found that only the b *Buffer pointer implements the io.Writer interface, so when we call the function in the sample code fmt.Fprint , we pass an address &b .

1234567
func Fprint (w io.) Writer, a ... Interface {})int, err error)  {p: = Newprinter () p.doprint (a) n, err = W.write (p.buf) p.free ()return }

This is the function fmt.Fprint of the implementation, its function is to write data a to an io.Writer interface implementation, specifically how to write, it is not concerned about, because it io.Writer will do, it only care can be written. w.Write(p.buf)called Wirte Method writes.

Finally, the b.WriteTo(os.Stdout) final data is exported to the standard os.Stdout , so that we can see the output, it receives an io.Writer interface type parameters, the beginning we talked about os.Stdout the implementation of this io.Writer interface, so it is possible to pass as a parameter.

Here we will find that many methods of receiving parameters are io.Writer interfaces, of course, there are io.Reader interfaces, which is interface-oriented programming, we do not have to focus on the implementation, only with the attention of this interface can do what things, if we switch to output to the file, then it is very easy, just use the os.File Type as a parameter. Any type that implements the interface can be used as a parameter.

In addition b.WriteTo to the method, we can also use the io.Reader interface method to Read achieve the data read.

123
var p [+]byten,err:=b.read (p[:]) fmt. Println (N,err,string(P[:n]))

This is the most primitive method, using the Read method, n is the number of bytes read, and then we print out the output.

Because byte.Buffer pointers implement io.Reader interfaces, we can also read data information in the following ways.

12
   Data,err:=ioutil. ReadAll (&b) fmt. Println (string(data), err)

ioutil.ReadAllInterface io.Reader is an interface parameter that indicates that all data can be read from any type that implements the io.Reader interface.

123456789101112131415161718
 func readall(r io. Reader, capacity int64) (b []byte, err error) {buf: = bytes. Newbuffer ( Make([]byte,0, capacity))//If The buffer overflows, we'll get bytes. Errtoolarge.//Return that as an error. Any other panic remains.defer  func() {e: =Recover()ifE = =Nil{return}ifPanicerr, OK: = E. (error); Ok && panicerr = = bytes. Errtoolarge {err = Panicerr}Else{Panic(e)}} () _, err = buf. Readfrom (R)returnBuf. Bytes (), err}

The above is the ioutil.ReadAll implementation of the source code, but also very simple, the basic principle is to create a byte.Buffer , through this byte.Buffer ReadFrom method, the io.Reader data in the reading, and finally through byte.Buffer the Bytes method to return the final read bytes of data information.

The entire stream read and write has been completely abstracted, io most of the operation and type of the package is based on these two interfaces, and of course, HTTP and other involved in data flow, file flow, etc., can be fully used io.Writer and io.Reader interface to represent, through the connection between the two interfaces, We can implement any data read and write.

"Go language Combat" reading notes, not to be continued, welcome to sweep code attention flysnow_org to the public or website http://www.flysnow.org/, the first time to see follow-up notes. If you feel helpful, share it with your friends and thank you for your support.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.