1
seers 2023-06-10 11:04:35 +08:00
defer 是在 return 前才调用
|
2
Assassinrx OP @seers 但是一般 error 里面就返回了
|
3
R0n1n 2023-06-10 11:11:12 +08:00
出错了也就不用再去关闭句柄了,所以一般是先判断 err 吧
|
4
zhs227 2023-06-10 11:16:11 +08:00
第一个 os.Open 如果返回了 err ,那么 file 必定是 nil ,这种情况下不需要 Close 。只有 err == nil 的情况下,才需要在最结尾 close 。
当然如果按你下面的写法也没错,实际上 file.Close 当 file==nil 的时候,会返回一个 ErrInvalid ,这个你看一下 go 的源码就清楚了。 |
5
twistedmeadows 2023-06-10 11:17:20 +08:00 via iPhone
gpt 答案:
在 Go 语言中,如果在尝试打开文件时返回的 err 不为 nil ,那么这意味着在打开文件的过程中出现了一些错误。在这种情况下,file 变量通常会是 nil ,所以你无法或者不需要调用 file.Close()。 全文: https://chat.openai.com/share/bb186187-feb5-4970-b36f-6c0914f6e668 |
6
lasuar 2023-06-10 11:17:40 +08:00
看下源码 不就知道了,正常的接口设计不会出现你说的情况
|
7
Assassinrx OP @R0n1n 所以我多想了一下,是 golang 都有这个标准,出现 err 就不需要管别的返回了,还是说 err 存在但是 file 也打开了的情况
|
8
Assassinrx OP @zhs227 源码是写的 nil ,但是可不可能在系统层面还是打开的,也就是文件里面的引用指针还是+1 了的情况,这块研究不深,所以想问问大佬们
|
9
Assassinrx OP @lasuar 我能理解,毕竟这个底层也是 golang 官方库,只是好奇的想确认下文件这块的操作流程是不是符合预期
|
10
Assassinrx OP @twistedmeadows 这么想了下也确实
|
11
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 的。 |
12
aeof 2023-06-10 11:26:12 +08:00 via Android
不可能出现
|
13
Assassinrx OP @zhs227 好像懂了。也就是 golang 这块 我只要做到正常的处理就行了,底层它内部调用的文件系统是否关闭了文件,我这边也处理不到了。原本是想了解下这个底层是否关闭了,影不影响上层处理。,从写 golang 逻辑下,正常写法就已经是完美了。
|
14
Assassinrx OP @aeof 行!
|
15
harrozze 2023-06-10 11:57:07 +08:00
@Assassinrx #8 既然用 go 的库,那么“如果 Open 返回的 err 不为 nil ,而实际系统层面文件是打开的”这件事情应该是 go 需要考虑的,甚至(如果真是这样的话)算是一个 bug 。
先别想这些细节上的优化,先把代码跑起来,遇到了再说。 |
16
Assassinrx OP @harrozze 确实是这样。至少代码层面开发者能做的都做到了。
|
17
admpubcom 2023-06-10 13:41:30 +08:00 via iPhone
代码就在面前,为什么不点进去看一下呢
|
18
Jirajine 2023-06-10 15:27:49 +08:00
你只要记住 golang 的 convention 是,调用一个会返回错误的函数时,只在检查完错误之后才能使用其他返回值。没有检查错误或错误不为 nil 时其他返回值都可以认为是无效的,使用此值可以看作 undefined behavior 。
这主要是因为 go 欠缺 union type 。 |
19
Assassinrx OP @admpubcom 我可能想的太多了,纯粹好奇问一下
|
20
Assassinrx OP @Jirajine 这个是的,确实能理解了
|
21
flyqie 2023-06-11 00:00:27 +08:00 via Android
|
22
Jirajine 2023-06-11 00:47:27 +08:00
@flyqie 这个我当然知道,所以说这是 convention ,convention 有例外是很正常的。
像这种情况在其他类型严格且表达能力足够的语言中,接口可以返回一个专门的 IOResult ,与普通的 Result 区分。 |
23
timpaik 2023-06-11 01:12:32 +08:00
约定俗成,标准库里直接可以认为这俩互斥,但没有类型系统保证,第三方库保险起见看看实现就好了
|
24
realpg 2023-06-11 02:22:15 +08:00
golang 提供的官方标准库里,出现了你设想的那种场景,那就是 bug ,golang 官方负责解决,你下层不用想能解决上层的问题。
你引用了的别人的三方库里出现这种问题,那是哪个库作者的 bug ,库作者负责解决这种问题,你下层不用想能解决上层的问题。 |
25
Assassinrx OP @timpaik ok ,了解
|
26
Assassinrx OP @realpg 确实是这个道理
|
27
lotusgrm 2023-07-25 17:10:29 +08:00
os.Open Go 源码如下:
func Open(name string) (*File, error) { return OpenFile(name, O_RDONLY, 0) } 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 } 从这里可以看到,如果 open file 的时候,出现了 error ,os.Open 返回的第一个值是 nil, 那么此时也就不需要再进行 close |