ioutil.ReadAll注意事项
现象
读取文件或者网络请求时,我们经常会遇到ioutil.ReadAll方法,但是这个方法虽然方便有时候却会导致一些性能问题。
我们往一个名为”test“的测试文件里简单写入两行字符串:
test
test
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
file, err := os.Open("test")
checkErr(err)
b, err := ioutil.ReadAll(file)
checkErr(err)
fmt.Println(string(b))
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
再看看输出:可以看到len只有9但是cap却有1536,我们只读取很少的内容却使用了这么多的内存,这在平时不会有问题,但是比如在网络应用当有大量请求过来时就容易导致内存严重浪费,严重时还会内存泄漏。
fmt.Println(len(b))
fmt.Println(cap(b))
输出:
9
1536
我们来看看它底层到底如何读取的:ReadAll调用了内部方法readAll
func ReadAll(r io.Reader) ([]byte, error) {
return readAll(r, bytes.MinRead)
}
解决办法bufio.Reader.Read
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.Open("test")
checkErr(err)
data := make([]byte, 1025)
r := bufio.NewReader(file)
r.Read(data)
fmt.Println(len(data))
fmt.Println(cap(data))
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
输出:
1025
1025