defer的执行顺序?
在Go语言中,defer
语句的执行顺序遵循“后进先出”(Last In, First Out, LIFO)原则,类似于栈的结构。具体来说:
当函数执行过程中出现多个defer
语句时,它们会按照在函数内部定义的逆序执行。也就是说,最后被定义(或执行)的defer
语句会首先被执行,而最早被定义(或执行)的defer
语句则最后执行。
例如:
func example() {
defer fmt.Println("First declared, third executed")
defer fmt.Println("Second declared, second executed")
// ... 函数体的其他代码 ...
defer fmt.Println("Third declared, first executed")
// ... 更多的函数体代码 ...
}
// 当调用example函数时,输出将是:
// Third declared, first executed
// Second declared, second executed
// First declared, third executed
defer
语句常用于资源的释放、解锁、关闭文件等操作,确保这些操作在函数返回前一定会被执行,不论函数是否出现异常或提前返回。
100G的文件, 统计出所有英文字母, 按照字母表顺序输出
由于100GB的文件无法一次性载入内存,我们需要采取逐块读取文件的方式来统计所有英文字母并按照字母表顺序输出。下面是一个简单的Go语言实现思路,考虑到性能和内存消耗,这里采用了滑动窗口和有序映射(sort.StringSlice)来累积统计结果。
package main
import (
"bufio"
"fmt"
"os"
"strings"
"unicode"
)
func countLettersFromFile(filename string) ([]string, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
counts := make(map[rune]int)
scanner := bufio.NewScanner(file)
buffer := make([]byte, 1024*1024) // 假设每次读取1MB的数据块
for scanner.Scan() {
// 将扫描的数据块转化为字符串
text := scanner.Text()
for _, r := range text {
if unicode.IsLetter(r) && unicode.IsLower(r) {
counts[r]++
}
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
// 将统计结果转化为字母及其出现次数的切片
var sortedLetters []string
for k, v := range counts {
sortedLetters = append(sortedLetters, fmt.Sprintf("%c:%d", k, v))
}
// 按字母顺序排序
sort.Slice(sortedLetters, func(i, j int) bool {
return sortedLetters[i] < sortedLetters[j]
})
return sortedLetters, nil
}
func main() {
letters, err := countLettersFromFile("your_100GB_file.txt")
if err != nil {
panic(err)
}
// 输出按字母顺序排列的统计结果
for _, l := range letters {
fmt.Println(l)
}
}
请注意,上面的代码仅处理小写字母,如需统计大小写字母,可以去掉unicode.IsLower(r)
的条件判断。另外,这个示例假设文件内容是UTF-8编码,如果是其他编码,需要相应地进行解码。
由于实际场景中处理100GB文件时要考虑的因素很多(如硬盘I/O性能、内存使用、运行时间等),上述代码可能需要进一步优化以适应实际情况。此外,统计结果是按照“字母:出现次数”的格式输出,若只输出字母,可以稍作修改。
最后编辑: kuteng 文档更新时间: 2024-04-02 09:53 作者:kuteng