Pointers 为什么接口类型没有';t提供一个;IsNil";方法? 首先让我们考虑以下内容: 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) }

Pointers 为什么接口类型没有';t提供一个;IsNil";方法? 首先让我们考虑以下内容: 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) },pointers,go,interface,null,Pointers,Go,Interface,Null,以下是输出: 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", contai

以下是输出:

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
对此的解释见

一个简单的解决方案是,如果接口对象包含
nil
值,则使
==nil
测试仅返回true。但这将违反
==
的可传递性,因为它将在
==
下断言两个值为零但接口类型不同的对象

但是,我想知道在所有接口类型上是否都应该有一个
IsNil()
方法来解决这个问题?

另一个示例是Go http客户端的这一行,它会意外地捕获您:

所以如果你这样称呼它

var body *bytes.Buffer
http.NewRequest(method, path, body)
您将得到一个nil指针异常,尽管从源代码的外观来看,这不应该发生

编辑

抱歉,我引用了错误的Go http源代码行,现在已更正。 但这个例子仍然成立

编辑2


我强调了我的问题,以明确我的问题。

首先阅读此相关问题:

通过与
nil
进行比较,可以检查接口值本身是否为
nil

如果要检查包装在非
nil
接口中的值是否为
nil
,可以使用反射:

请参见此修改后的示例:

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{})
}
输出(在上尝试):

如果您想要一个“统一的”
IsNil()
函数,它告诉您其中一个是否为
nil

func IsNil(i interface{}) bool {
    return i == nil || reflect.ValueOf(i).IsNil()
}

首先阅读这个相关问题:

通过与
nil
进行比较,可以检查接口值本身是否为
nil

如果要检查包装在非
nil
接口中的值是否为
nil
,可以使用反射:

请参见此修改后的示例:

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{})
}
输出(在上尝试):

如果您想要一个“统一的”
IsNil()
函数,它告诉您其中一个是否为
nil

func IsNil(i interface{}) bool {
    return i == nil || reflect.ValueOf(i).IsNil()
}

这里有一个函数,用于报告接口是否包含任何
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
    }
}

这里有一个在操场上工作的示例:

这里有一个函数,用于报告接口是否包含任何
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
    }
}

这里有一个在操场上工作的例子:

以下内容显然是基于Paul Hankin的回答、icza写的一点内容以及reflect/value.go的来源,其中定义了
func(v value)IsNil()bool
。不要相信消息来源,我是一个利用坎宁安定律的新手!我会只是发表评论,但我甚至没有50分(-:


以下内容显然是基于Paul Hankin的回答、icza所写的一点内容以及reflect/value.go的来源,其中定义了
func(v value)IsNil()
。不要相信来源,我是一个利用坎宁安定律的新手!我只会发表评论,但我甚至没有50分(-:


请注意,这个问题是关于为什么Go中没有提供“IsNil()”作为方法。“重复”问题不是这样的。您可以对所有接口值使用
==nil
来测试它们是否相等。您案例中的混淆来自
进程()内部
检查接口值是否为
nil
,而在
main()
函数中检查非接口的指针值。当指针传递给函数时,接口值是自动隐式创建的。请注意,这个问题是关于为什么Go中没有提供“IsNil()”作为方法。“duplicated”问题不是这样的。您可以在所有接口值上使用
==nil
来测试它们是否相等。您案例中的混淆来自
process()
内部,您在
main()中检查接口值是否为
nil
function您检查非接口的指针值。当指针传递给函数时,接口值会自动隐式创建。嗨,icza,谢谢您的回答。我不知道该方法在reflect包内。嗨,icza,谢谢您的回答。我不知道该方法在reflect包内。