面试题答案
一键面试- 逐行处理而非一次性读取:
- 当读取文件内容时,避免一次性将整个文件读入内存。例如,在处理文本文件时,可以使用
bufio.Scanner
逐行读取。
file, err := os.Open(filePath) if err!= nil { // 错误处理 } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() // 处理每一行内容 } if err := scanner.Err(); err!= nil { // 错误处理 }
- 当读取文件内容时,避免一次性将整个文件读入内存。例如,在处理文本文件时,可以使用
- 及时释放资源:
- 对于打开的文件,在使用完毕后及时关闭。使用
defer
关键字确保文件在函数结束时关闭,避免文件描述符泄漏和内存占用。如上述代码中,使用defer file.Close()
。
- 对于打开的文件,在使用完毕后及时关闭。使用
- 优化文件信息存储结构:
- 如果需要存储文件信息,避免使用无限制增长的切片或映射。例如,如果只是需要记录文件名,可以考虑使用
sync.Map
(适用于并发场景)或者普通的map
,但要注意在不再需要时及时清理。 - 对于大型文件系统遍历,假设只关心文件路径和文件大小,可以定义一个轻量级结构体:
type FileInfoLite struct { Path string Size int64 }
- 然后使用切片存储这些信息:
var fileInfos []FileInfoLite err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error { if err!= nil { return err } if!info.IsDir() { fileInfos = append(fileInfos, FileInfoLite{Path: path, Size: info.Size()}) } return nil }) if err!= nil { // 错误处理 }
- 如果需要存储文件信息,避免使用无限制增长的切片或映射。例如,如果只是需要记录文件名,可以考虑使用
- 限制缓冲区大小:
- 在进行文件读写操作时,合理设置缓冲区大小。例如,在写入文件时,可以使用
bufio.NewWriterSize
来设置缓冲区大小。
file, err := os.Create(outputPath) if err!= nil { // 错误处理 } defer file.Close() writer := bufio.NewWriterSize(file, 4096) // 设置缓冲区为4KB _, err = writer.WriteString("some data") if err!= nil { // 错误处理 } err = writer.Flush() if err!= nil { // 错误处理 }
- 在进行文件读写操作时,合理设置缓冲区大小。例如,在写入文件时,可以使用
- 并发控制:
- 如果采用并发遍历文件,要注意控制并发数,避免因过多的并发操作导致内存占用过高。可以使用
sync.WaitGroup
和channel
来实现。
var wg sync.WaitGroup maxConcurrency := 10 semaphore := make(chan struct{}, maxConcurrency) err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error { if err!= nil { return err } if!info.IsDir() { semaphore <- struct{}{} wg.Add(1) go func(p string) { defer func() { <-semaphore wg.Done() }() // 处理文件 }(path) } return nil }) if err!= nil { // 错误处理 } wg.Wait()
- 如果采用并发遍历文件,要注意控制并发数,避免因过多的并发操作导致内存占用过高。可以使用