一次一个同事给我发了一段简单的代码,问我这段代码有什么问题?
package main
import (
"fmt"
"os"
)
func main() {
f, err := os.Open("/test.txt")
if err != nil {
fmt.Println(err)
}
fmt.Println(f.Name(), "opened successfully")
}
看到这段代码后不加思索的回答,文件没有close,他说错,可能当时我们没在一个频道上,“err处理没有return”。
又仔细的看了下代码,发现err的处理代码块后使用了f.Name(),这个是存在问题的,因为当open发生错误时,返回的文件句柄则为nil,下文直接使用f.Name()。这种错误对于初学者经常会犯,改进的方式也很多,只要保证运行f.Name()的得到的f不为nil即可。
可以在发生错误时,可以return或者os.Exit(-1) 也或下文的f.Name()放到else逻辑块中。
具体的处理方式要根据对报错的容忍度来处理
package main
import (
"fmt"
"os"
)
func main() {
for i := 1; i <= 4865; i++ {
f, err := os.Open("./test.txt")
if err != nil {
fmt.Println(err)
}
fmt.Println(f.Name(), "opened successfully", i)
}
fmt.Scanln()
}
执行结果
发生了猜想中的问题,刚查看最大文件描述符是4864,这里只打开了4861个,为什么少了三个?
那么就是该程序默认占用了三个
通过lsof查下进程打开的描述符情况
发现程序会默认打开三个系统文件描述符
也就是标准输入,标准输出,错误输出
这样的解释就可以自说其圆了,真的是这样么?
以下是维基百科对文件描述符的叙述
对文件的描述符的探索,可以画上一个句号了。
在产看进程关联的文件时,发现有多出以上四个,这些有什么?这个问题作为一个遗留问题抛在这里,等待有心去探索
通过以上的试验和验证,在程序打开文件后,记得close
完善后的最终处理代码
package main
import (
"fmt"
"os"
)
func main() {
for i := 1; i <= 50000; i++ {
f, err := os.Open("./test.txt")
defer f.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(f.Name(), "opened successfully", i)
}
fmt.Scanln()
}
喜欢请关注“云端漫记", 持续为你更新
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。