golang 可能出现文件打开但是报错的情况吗

2023-06-10 10:45:37 +08:00
 Assassinrx
正常打开文件的模式代码就是这样,我想问下各位大佬可能出现 err 不为空但是文件被打开的情况吗

file, err := os.Open("filename.txt")
if err != nil {
// 处理错误
}
defer file.Close()

因为我想的是可能这么写更好些?

file, err := os.Open("filename.txt")
defer file.Close() // defer 写在 err 前面
if err != nil {
// 处理错误
}
1648 次点击
所在节点    Go 编程语言
27 条回复
seers
2023-06-10 11:04:35 +08:00
defer 是在 return 前才调用
Assassinrx
2023-06-10 11:10:45 +08:00
@seers 但是一般 error 里面就返回了
R0n1n
2023-06-10 11:11:12 +08:00
出错了也就不用再去关闭句柄了,所以一般是先判断 err 吧
zhs227
2023-06-10 11:16:11 +08:00
第一个 os.Open 如果返回了 err ,那么 file 必定是 nil ,这种情况下不需要 Close 。只有 err == nil 的情况下,才需要在最结尾 close 。
当然如果按你下面的写法也没错,实际上 file.Close 当 file==nil 的时候,会返回一个 ErrInvalid ,这个你看一下 go 的源码就清楚了。
twistedmeadows
2023-06-10 11:17:20 +08:00
gpt 答案:
在 Go 语言中,如果在尝试打开文件时返回的 err 不为 nil ,那么这意味着在打开文件的过程中出现了一些错误。在这种情况下,file 变量通常会是 nil ,所以你无法或者不需要调用 file.Close()。

全文:
https://chat.openai.com/share/bb186187-feb5-4970-b36f-6c0914f6e668
lasuar
2023-06-10 11:17:40 +08:00
看下源码 不就知道了,正常的接口设计不会出现你说的情况
Assassinrx
2023-06-10 11:19:18 +08:00
@R0n1n 所以我多想了一下,是 golang 都有这个标准,出现 err 就不需要管别的返回了,还是说 err 存在但是 file 也打开了的情况
Assassinrx
2023-06-10 11:21:29 +08:00
@zhs227 源码是写的 nil ,但是可不可能在系统层面还是打开的,也就是文件里面的引用指针还是+1 了的情况,这块研究不深,所以想问问大佬们
Assassinrx
2023-06-10 11:22:55 +08:00
@lasuar 我能理解,毕竟这个底层也是 golang 官方库,只是好奇的想确认下文件这块的操作流程是不是符合预期
Assassinrx
2023-06-10 11:24:28 +08:00
@twistedmeadows 这么想了下也确实
zhs227
2023-06-10 11:25:01 +08:00
Close 的代码你看一下就懂了,返回为 nil 的时候根本就没涉及到资源处理。
func (f *File) Close() error {
if f == nil {
return ErrInvalid
}
return f.file.close()
}


Open 的代码:
func OpenFile(name string, flag int, perm FileMode) (*File, error) {
testlog.Open(name)
f, err := openFileNolog(name, flag, perm)
if err != nil {
return nil, err
}
f.appendMode = flag&O_APPEND != 0

return f, nil
}

要么 f 有值,err==nil ,要么 f==nil ,err 有值。只有这两种可能。而 err 有值的情况下,f==nil 也是不用 close 的。
aeof
2023-06-10 11:26:12 +08:00
不可能出现
Assassinrx
2023-06-10 11:33:20 +08:00
@zhs227 好像懂了。也就是 golang 这块 我只要做到正常的处理就行了,底层它内部调用的文件系统是否关闭了文件,我这边也处理不到了。原本是想了解下这个底层是否关闭了,影不影响上层处理。,从写 golang 逻辑下,正常写法就已经是完美了。
Assassinrx
2023-06-10 11:34:22 +08:00
@aeof 行!
harrozze
2023-06-10 11:57:07 +08:00
@Assassinrx #8 既然用 go 的库,那么“如果 Open 返回的 err 不为 nil ,而实际系统层面文件是打开的”这件事情应该是 go 需要考虑的,甚至(如果真是这样的话)算是一个 bug 。

先别想这些细节上的优化,先把代码跑起来,遇到了再说。
Assassinrx
2023-06-10 13:23:55 +08:00
@harrozze 确实是这样。至少代码层面开发者能做的都做到了。
admpubcom
2023-06-10 13:41:30 +08:00
代码就在面前,为什么不点进去看一下呢
Jirajine
2023-06-10 15:27:49 +08:00
你只要记住 golang 的 convention 是,调用一个会返回错误的函数时,只在检查完错误之后才能使用其他返回值。没有检查错误或错误不为 nil 时其他返回值都可以认为是无效的,使用此值可以看作 undefined behavior 。
这主要是因为 go 欠缺 union type 。
Assassinrx
2023-06-10 17:22:32 +08:00
@admpubcom 我可能想的太多了,纯粹好奇问一下
Assassinrx
2023-06-10 17:24:19 +08:00
@Jirajine 这个是的,确实能理解了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/947492

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX