ioutil.go
这个包平时就用得很多了,就那几个函数,很简单的实现。值得一说的是 readAll 函数中的几行
// src/io/ioutil/ioutil.go ---- line 16// readAll reads from r until an error or EOF and returns the data it read// from the internal buffer allocated with a specified capacity.func readAll(r io.Reader, capacity int64) (b []byte, err error) {var buf bytes.Buffer// If the buffer overflows, we will get bytes.ErrTooLarge.// Return that as an error. Any other panic remains.defer func() {e := recover()if e == nil {return}if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {err = panicErr} else {panic(e)}}()if int64(int(capacity)) == capacity {buf.Grow(int(capacity))}_, err = buf.ReadFrom(r)return buf.Bytes(), err}
注意上面代码块的第 19 到 21 行,对 capacity 的判断,个人理解是因为后续要把 int(capacity) 传给 buf.Grow 函数,而在 buf.Grow 函数中如果参数小于零是会 panic 的,所以这里是在检测 int64 的 capacity 是否对 int32 有溢出,是否在转换成 int 后会变成负数,如果不会出现溢出再传给 buf.Grow 以确保安全
tempfile.go
这个文件就很酷了,写了两年 Go 的我居然现在才发现。这个文件提供了一些用于创建临时文件或临时目录的函数,当然这个所谓的临时文件不是说程序结束就给删掉了,而是名字随机化以免和其他文件冲突,用于不重要地缓存一些内容,随时可删除的那种,就像 /tmp/ 中的文件。
至于写了两年居然都没遇到这种需求?不不,我有这种需求的时候都是自己实现的,没想过原来标准库就提供了这种功能。
具体的实现,值得一说的也就一个随机数生成,但是不想看,记住它真的很随机生成的文件名不会重复就行了
// src/io/ioutil/tempfile.go ---- line 27func nextRandom() string {randmu.Lock()r := randif r == 0 {r = reseed()}r = r*1664525 + 1013904223 // constants from Numerical Recipesrand = rrandmu.Unlock()return strconv.Itoa(int(1e9 + r%1e9))[1:]}
还出现了几个 Magic Number 就更没有深挖的欲望了。
