后端青训营day3 | 青训营笔记

38 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第3天

今天短短两小时的内容, 我需要用两个星期的时间来治愈.

今天先补一下Go基础.

1. package io

在 io 包中最重要的两个接口: ReaderWriter 接口.

只要满足这两个接口, 他就可以使用IO包的功能

Reader 接口的方法集只包含一个 Read 方法,因此,所有实现了 Read 方法的类型都满足 io.Reader 接口.

func ReadFrom(reader io.Reader, num int) ([]byte, error) {
    p := make([]byte, num)
    n, err := reader.Read(p)
    if n > 0 {
        return p[:n], nil
    }
    return p, err
}

ReadFrom 函数将 io.Reader 作为参数,也就是说,ReadFrom 可以从任意的地方读取数据,只要来源实现了 io.Reader 接口。比如,我们可以从标准输入、文件、字符串等读取数据,示例代码如下:

// 从标准输入读取
data, err = ReadFrom(os.Stdin, 11)
​
// 从普通文件读取,其中 file 是 os.File 的实例
data, err = ReadFrom(file, 9)
​
// 从字符串读取
data, err = ReadFrom(strings.NewReader("from string"), 12)

一个小细节: io.EOF 变量的定义:var EOF = errors.New("EOF"),是 error 类型。根据 reader 接口的说明,在 n > 0 且数据被读完了的情况下,返回的 error 有可能是 EOF 也有可能是 nil。

Writer接口的定义如下:

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

同样的, 所有实现了Write方法的类型都实现了 io.Writer 接口。

os 包中我们能看到这样的代码:

var (
    Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
    Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
    Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

也就是说,Stdin/Stdout/Stderr 只是三个特殊的文件类型的标识(即都是 os.File 的实例),我们可以知道,os.File 同时实现了这两个接口。

虽然Go文档中还没有直接列出实现了某个接口的所有类型。不过我们可以通过godoc -analysis 来列出都有哪些类型实现了某个接口。