За комментарий:
Я использую значение upstreamDebugFile в качестве io.WriteCloser. Я считаю, что он не дает равенства с nil, даже если файл не установлен.
io.WriteCloser
является экземпляром интерфейса . Между тем, os.OpenFile
возвращает *os.File
, что является указателем на 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)
}
Go Playground output:
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
имеет назначенный тип , вы не можете просто проверить его целиком. Вы должны начать тестировать его фактическое значение, его базовый тип, как в этой программе:
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)
}
Попробуйте его на игровой площадке Go. Но учтите, что если 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
напрямую.