首先让我们考虑以下几点:
func process(body io.Reader) {
fmt.Printf("body == nil ? %+v\n", body == nil)
}
func main() {
var body *bytes.Buffer
fmt.Printf("body == nil ? %+v\n", body == nil)
process(body)
process(nil)
}
这是输出:
body == nil ? true
body == nil ? false // Did you get this right?
body == nil ? true
另一个例子:
type Container struct {
Reader io.Reader
}
func processContainer(container Container) {
fmt.Printf("container.Reader == nil ? %+v\n", container.Reader == nil)
}
func main() {
var body *bytes.Buffer
processContainer(Container{Reader: body})
processContainer(Container{Reader: nil})
}
输出:
container.Reader == nil ? false // Did you get this right?
container.Reader == nil ? true
对此的解释是https://golang.org/doc/faq#nil_error。
一个天真的解决方案是,如果接口对象包含== nil
值,则nil
测试只返回true。但是这会违反==
的传递性,因为它会在==
下断言两个nil值但接口类型不同的对象。
但是,我想知道是否应该在所有接口类型上使用IsNil()
方法来解决此问题?
另一个例子,来自Go http客户端的这一行可能会意外地抓住你:
https://github.com/golang/go/blob/master/src/net/http/client.go#L545
所以,如果你这样称呼它
var body *bytes.Buffer
http.NewRequest(method, path, body)
你会得到一个nil指针异常,即使从源代码的外观来看,这不应该发生。
修改
抱歉,我引用了Go http源的错误行,现已更正。 但这个例子仍然存在。
修改2
我突出了我的问题,以明确我在问什么。
答案 0 :(得分:3)
首先阅读此相关问题:Hiding nil values, understanding why golang fails here
您可以通过将界面值与nil
进行比较来检查界面值本身是否为nil
。
如果您想检查非nil
界面中包含的值是否为nil
,您可以使用反射:reflect.Value.IsNil()
。
见这个修改过的例子:
func process(body io.Reader) {
fmt.Printf("process(): body == nil ? %t\n", body == nil)
if body != nil {
fmt.Println("\tINSIDE IsNil():", reflect.ValueOf(body).IsNil())
}
}
func main() {
var body *bytes.Buffer
fmt.Printf("main(): body == nil ? %t\n", body == nil)
process(body)
process(nil)
process(&bytes.Buffer{})
}
输出(在Go Playground上尝试):
main(): body == nil ? true
process(): body == nil ? false
INSIDE IsNil(): true
process(): body == nil ? true
process(): body == nil ? false
INSIDE IsNil(): false
如果您想要一个“统一”IsNil()
函数,该函数可以判断它们是nil
:
func IsNil(i interface{}) bool {
return i == nil || reflect.ValueOf(i).IsNil()
}
答案 1 :(得分:2)
这是一个报告接口是否包含任何nil
的函数。请注意,reflect.Value.IsNil()
会在类型没有nil值时感到恐慌,因此在调用该类型之前必须进行一些检查。
func isNil(x interface{}) bool {
v := reflect.ValueOf(x)
switch v.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Slice:
return v.IsNil()
default:
return false
}
}
这是操场上的一个工作示例:https://play.golang.org/p/RHzu3VVj4Zd
答案 2 :(得分:-1)
以下内容显然基于Paul Hankin的回答,一点点icza的写作以及reflect / value.go的来源,其中定义了 Warning FailedMount 8s (x2 over 21s) kubelet, gke-windows-node-pool-e4e7a7bf-f2pc Unable to attach or mount volumes: unmounted volumes=[smb-volume], unattached volumes=[default-token-jf28b smb-volume]: failed to get Plugin from volumeSpec for volume "smb-volume" err=no volume plugin matched
。不相信消息来源,我是利用坎宁安法则的新手!我本来可以发表评论,但我什至没有50分(-:
func (v Value) IsNil() bool