了解Golang的writer/reader接口

Understanding Golang's writer/reader interface

是什么

首先writer/reader都是接口

1
2
3
4
5
6
type Writer interface {
  Write(p []byte) (n int, err error)
}
type Reader interface {
  Read(p []byte) (n int, err error)
}

他们各有一个动词的方法——读和写,那么就都需要一个宾语,也就是读谁写谁,从接口中是看不到宾语的,而接口在使用时肯定是要通过结构体实现的,所以这个宾语就在结构体中。

比如写信,信就是宾语,信.Write(字),就把字写到了信中。用代码实现如下:

1
2
3
4
5
6
7
type LetterWriter struct {
  Letter []byte
}
func (l *LetterWriter) Write(p []byte) (n int, err error) {
  l.Letter = append(l.Letter, p...)
  return len(p), nil
}

类似的,读信:

1
2
3
4
5
6
7
8
type LetterReader struct {
  Letter []byte
}
func (l *LetterReader) Read(p []byte) (n int, err error) {
  n = copy(p, l.Letter)
  l.Letter = l.Letter[n:]
  return n, nil
}

对于writer和reader,都在结构体中准备了一个字段

使用:

1
2
3
4
5
6
7
8
9
func main() {
  var w LetterWriter
  w.Write([]byte("hello"))
  fmt.Println(w.Letter)
  
  var r LetterReader
  r.Letter = new([]byte, 4)
  
}
1
2
3
4
5
6
7
type Writer struct {
   buf []byte
}
func (w *Writer) Write(p []byte) (n int, err error) {
   w.buf = append(w.buf, p...)
   return len(p), nil
}
1
2
3
4
5
6
func d() {
  reader := newXReader(source)
  target := make([]byte, length)
  n, err := reader.Read(target)
  fmt.Println(target)
}

将source的值写入target中,Read方法调用一次,读取n(n<=length)个字节的数据到target切片中

1
2
3
4
5
6
func d() {
  target := bytes.NewBufferString("hello")
  w := newXWriter(target)
  source := "world"
  w.Write(source)
}

target是一个容器,Writer的Write方法,会将参数写入source到容器中。

这两个概念理解起来有点绕。把writer或reader理解为一个容器,往里面加东西就是write,从里面取东西就是read

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func d() {
	req, err := http.NewRequest("POST", "zentao.77hub.com/zentao/bug-edit-"+"66738"+".html", strings.NewReader(body))

	if req != nil {
		req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	}
	a := newChanWriter("a")
	err = req.Header.Write(a)
	if err != nil {
		return
	}
	fmt.Println(a)
}

常用reader/writer

  1. Buffer实现了Reader和Writer接口,可以直接使用
1
2
3
4
s := "Hello"
buf := bytes.NewBufferString(s)
fmt.Fprint(buf, ", World!")
fmt.Println(buf.String())
  1. bufio包中的Reader
1
readline

参考资料

https://www.flysnow.org/2017/05/08/go-in-action-go-reader-writer.html https://www.jianshu.com/p/cb12e88c60d6 https://segmentfault.com/a/1190000015591319 https://juejin.cn/post/6976841033795502093 https://www.bilibili.com/read/cv9179650

参考资料

updatedupdated2022-08-162022-08-16