【转】io.Reader in depth
So this:
func Reverse(s string) (string, error)
Could become:
func Reverse(r io.Reader) io.Reader
----------------------------
io.Reader in depth
Single method interfaces end up being extremely powerful — more so than even the language creators thought.
This article aims to convince you to use io.Reader in your own code wherever you can.
Let’s have a look at io.Reader:
type Reader interface {
Read(p []byte) (n int, err error)
}
Pretty simple; a Reader is any type that implements the `Read` method.
Check out the comments from the standard library documentation for a little more context for Reader.
For those unfamiliar with these interfaces; you pass in a slice of bytes, and Read is asked to fill it with its data — which is does until it runs out of data. It returns the number of bytes read (in `n`) or an error if something goes wrong. Additionally, if it has finished reading, it will return a special marker error called `io.EOF` (end of file).
Examples of readers
There are many kinds of Reader types available in the standard library, and you’ve almost certainly used at least one of them.
If you open a file for reading, the object returned is an `os.File`, which is a Reader (it implements the Read method):
var r io.Reader
var err error
r, err = os.Open("file.txt")
You can also make a Reader from a normal string using `strings.NewReader`:
var r io.Reader
r = strings.NewReader("Read will return these bytes")
The body data from an `http.Request` is a Reader:
var r io.Reader
r = request.Body
A bytes.Buffer is a Reader:
var r io.Reader
var buf bytes.Buffer
r = &buf
There are many more throughout the standard library — and in most third-party packages too, since it’s good practice to use them wherever you can.
Using readers
Now we have a few Reader types — let’s explore ways in which they can be used.
You can read from them directly (this turns out to be the least useful use case):
p := make([]byte, 256)
n, err := r.Read(p)
`ioutil.ReadAll` lets you read everything from a Reader, and get the raw []byte data:
b, err := ioutil.ReadAll(r)
`io.Copy` lets you read ALL bytes from an io.Reader, and write it to an io.Writer:
n, err := io.Copy(w, r)
The JSON decoder lets you decode directly from a Reader:
err := json.NewDecoder(r).Decode(v)
If you’re reading bytes that have been gzipped, you can wrap the io.Reader in a gzip.Reader:
r = gzip.NewReader(r)
Now reading from the new reader will decompress as you read.
Take io.Reader when you can
If you’re designing a package or utility (even if it’s an internal thing that nobody will ever see) rather than taking in strings or []byte slices, consider taking in an io.Reader if you can for data sources. Because suddenly, your code will work with every type that implements io.Reader.
So this:
func Reverse(s string) (string, error)
Could become:
func Reverse(r io.Reader) io.Reader
Then if someone wants to use it with a string, they can:
r = Reverse(strings.NewReader("Make me backwards"))
But they can also use it with a file:
f, err := os.Open("file.txt")
if err != nil {
log.Fatalln(err)
}
r = Reverse(f)
Or a web request:
func handle(w http.ResponseWriter, r *http.Request) { rev := Reverse(r.Body) // etc...
}
Use io.Reader (and io.Writer) whenever you’re dealing with streams of data. And this goes for all single method interfaces from the standard library.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2020-11-12 postgresql 的value 子句——VALUES(0)
2020-11-12 【原文】PostgreSQL中RECURSIVE递归查询使用总结
2017-11-12 ubuntu How do I configure proxies without GUI?
2017-11-12 Ubuntu server命令行配置shadowsocks全局代理
2015-11-12 postgres 错误duplicate key value violates unique constraint 解决方案