从源码学习 Go 标准库(一):fmt - scan(4)
2023-12-19 06:09:09
从源码学习 Go 标准库(一):fmt - scan(4)
在上一篇文章中,我们学习了 scan.go 中一个十分重要的类型:Format 。这一篇文章,我们将学习如何使用 Format 类型去真正地执行扫描操作。
scan.go 文件中实现了两个与扫描操作有关的类型:Scanner 和 scanner 。
Scanner 类型是一个接口类型,定义了扫描操作最基本的方法:
type Scanner interface {
Scan(...interface{}) error
Scanln(...interface{}) error
}
scanner 类型实现了 Scanner 接口,并包含了实际执行扫描操作的具体方法。接下来,我们就逐个学习这些方法。
func (s *scanner) Scan
*func (s scanner) Scan 方法执行一个或多个参数的扫描操作。如果扫描成功,则返回 nil ;否则,返回一个错误。
Scan 方法的具体实现如下:
func (s *scanner) Scan(a ...interface{}) (err error) {
s.err = nil
s.lazyInit()
for i, v := range a {
err = s.scanOne(v, i == len(a)-1)
if err != nil {
return err
}
}
return nil
}
Scan 方法首先会调用 lazyInit 方法,进行一些必要的初始化操作。然后,它会遍历参数列表,依次调用 scanOne 方法对每个参数执行扫描操作。如果扫描操作失败,则 Scan 方法会返回一个错误。
func (s *scanner) Scanln
*func (s scanner) Scanln 方法与 *func (s scanner) Scan 方法类似,唯一的区别在于,Scanln 方法会在扫描操作完成后读取并丢弃输入流中的剩余内容(直到遇到换行符为止)。
Scanln 方法的具体实现如下:
func (s *scanner) Scanln(a ...interface{}) (err error) {
if err = s.Scan(a...); err == nil {
return s.skipLine()
}
return
}
总结
fmt 包中的扫描操作由 Scanner 接口和 scanner 类型实现。Scanner 接口定义了扫描操作的基本方法,而 scanner 类型则实现了这些方法并包含了实际执行扫描操作的具体方法。
在下一篇文章中,我们将分析完 fmt 包中与扫描操作相关的 scan 和 error 类型,给整个 fmt 包做个收尾。