go里面 interface 是否为nil
代码片段
type AAA interface {
GetName() string
}
type aaa struct {
name string
}
func (a *aaa) GetName() string {
fmt.Println("进来了")
return a.name
}
func newAAA() any {
var a *aaa = nil
return a
}
func demo() {
// 踩坑的一天
anyA := newAAA()
if anyA == nil {
fmt.Println("anyA 是 nil")
} else {
fmt.Println("anyA 不是 nil")
}
// =========================================================
A, Ok := anyA.(AAA)
if Ok {
fmt.Println("anyA 是 AAA")
} else {
fmt.Println("anyA 不是 AAA")
}
if A == nil {
fmt.Println("A 是 nil")
} else {
fmt.Println("A 不是 nil")
A.GetName()
}
}
总结:
代码中,newAAA
函数返回了一个 *aaa
类型的 nil
指针,但是由于它是作为 any
类型(即 interface{}
)返回的,所以尽管它内部的值是 nil
,anyA
本身并不是 nil
。这是因为接口在 Go 中是由动态类型和动态值组成的,当仅动态值为 nil
时,接口本身并不会被认为是 nil
。
在 demo
函数中,这种情况的处理如下:
-
当检查
anyA == nil
时,结果为false
,因为anyA
内部包含的动态类型是*aaa
,并不是无类型的nil
。所以会打印"anyA 不是 nil"
。 -
接下来的类型断言
A, Ok := anyA.(AAA)
检查anyA
是否实现了AAA
接口。由于*aaa
类型实现了AAA
接口(因为*aaa
有一个定义的GetName
方法),类型断言会成功,变量Ok
为true
。所以会打印"anyA 是 AAA"
。 -
尽管
A
是从一个为nil
的*aaa
类型变量断言出的AAA
接口类型,A
本身也并不会是nil
,因为它携带了*aaa
的类型信息。所以,if A == nil
的检查结果会是false
。会打印"A 不是 nil"
,然后执行A.GetName()
。 -
在调用
A.GetName()
时,会发生运行时错误,因为实际上A
是nil
,当试图通过nil
指针调用一个方法。在这里的GetName
方法的实现中,如果接收器是nil
,就会引发 panic,因为在方法内部试图访问a.name
,这需要对nil
指针进行解引用操作。
所以,执行 demo()
函数的结果将是:
anyA 不是 nil
anyA 是 AAA
A 不是 nil
进来了
紧接着的是程序会因为 nil
的解引用崩溃。
对于 demo
函数,它展示了如何检查一个变量是否实现了某个接口,然而,关于接收器为 nil
的方法调用,必须特别小心。在 Go 中,允许 nil
接收器的方法调用,只要方法内部正确处理 nil
。但在很多情况下,这可能不是预期的行为,按照正常的思路一般都会认为接收器不会是nil,这就是需要注意的点。
一个更健壮的做法是在设计接口和方法时避免这种状况,例如不返回包含 nil
的接口类型,或者在方法内部检查接收器是否为 nil
。这样,调用者就不需要编写复杂的 nil
检查逻辑,代码的安全性和可读性都会提高。
一点点笔记,以便以后翻阅。
原文地址:https://blog.csdn.net/qq_44111597/article/details/144056569
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!