有没有一种方法可以检查Go中文件描述符是否有效(在初始打开操作之后)?
考虑以下代码片段(如果在命令行标志中指定了打开调试文件的地方)
upstreamDebug := flag.String("upstream_debug", "", "File for debugging")
flag.Parse()
var upstreamDebugFile os.File
if *upstreamDebug != "" {
upstreamDebugFile, err := os.OpenFile(*upstreamDebug, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
log.Println("writing to", upstreamDebugFile.Name())
defer upstreamDebugFile.Close()
}
到目前为止,太好了。但是稍后,我们希望在&且仅当它是有效的描述符时才写到upstreamDebugFile
-在if {..}子句之外。
是否有测试其有效性的方法? lib中似乎没有任何内置方法。与nil的比较
if upstreamDebugFile == nil {
出现错误
cannot convert nil to type os.File
答案 0 :(得分:1)
每条评论:
我将上游调试文件值用作io.WriteCloser。我发现即使未设置文件,它也不等于nil。
An io.WriteCloser
is an instance of an interface。同时,os.OpenFile
返回*os.File
,即a pointer to a struct
。该实现接口,但不是该接口类型的值。对于某些用途而言,这没什么大不了的,因为它实现接口这一事实意味着您可以将*os.File
值存储在io.WriteCloser
中。
但是,如以下程序所示,您必须谨慎测试io.WriteCloser
是否为零,因为它通常不是:
package main
import (
"fmt"
"io"
"os"
)
func main() {
var iface io.WriteCloser
p, err := os.OpenFile("/bad/foo", os.O_CREATE, 0666)
if err != nil {
fmt.Println(err)
}
fmt.Printf("before assignment, iface = %#v, and iface == nil => %t\n", iface, iface == nil)
iface = p
fmt.Printf("after assignment, iface = %#v, and iface == nil => %t\n", iface, iface == nil)
fmt.Printf("meanwhile p == nil => %t\n", p == nil)
}
open /bad/foo: No such file or directory
before assignment, iface = <nil>, and iface == nil => true
after assignment, iface = (*os.File)(nil), and iface == nil => false
meanwhile p == nil => true
iface
一旦分配了 type ,就不能对它进行整体测试。您必须像下面的程序中一样,开始测试其基础类型的实际值:
package main
import (
"fmt"
"io"
"os"
)
func main() {
var iface io.WriteCloser
p, err := os.OpenFile("/bad/foo", os.O_CREATE, 0666)
if err != nil {
fmt.Println(err)
}
iface = p
fmt.Printf("iface.(*os.File) == nil => %t\n", iface.(*os.File) == nil)
}
Try it on the Go Playground.,但请注意,如果从未为iface
分配类型为*os.File
的值,则类型声明将失败!
如果要存储的内容始终是*os.File
,只需声明变量为*os.File
:
var foo *os.File
if somecond {
var err error
foo, err = os.OpenFile(... arguments ...)
...
}
// later:
if foo != nil {
...
}
请注意,您也可以执行以下操作:
var iface io.WriteCloser
...
if somecond {
p, err := os.OpenFile(...)
...
if p != nil {
iface = p
}
}
,现在iface == nil
就足够了。但是除非您真的打算使用多个不同的基础io.WriteCloser
实现,否则请保持简单并直接使用*os.File
。