![]() | 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 PRO 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 |