当前位置: 首页 > article >正文

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{})返回的,所以尽管它内部的值是 nilanyA 本身并不是 nil。这是因为接口在 Go 中是由动态类型和动态值组成的,当仅动态值为 nil 时,接口本身并不会被认为是 nil

demo 函数中,这种情况的处理如下:

  1. 当检查 anyA == nil 时,结果为 false,因为 anyA 内部包含的动态类型是 *aaa,并不是无类型的 nil。所以会打印 "anyA 不是 nil"

  2. 接下来的类型断言 A, Ok := anyA.(AAA) 检查 anyA 是否实现了 AAA 接口。由于 *aaa 类型实现了 AAA 接口(因为 *aaa 有一个定义的 GetName 方法),类型断言会成功,变量 Oktrue。所以会打印 "anyA 是 AAA"

  3. 尽管 A 是从一个为 nil*aaa 类型变量断言出的 AAA 接口类型,A 本身也并不会是 nil,因为它携带了 *aaa 的类型信息。所以,if A == nil 的检查结果会是 false。会打印 "A 不是 nil",然后执行 A.GetName()

  4. 在调用 A.GetName() 时,会发生运行时错误,因为实际上 Anil,当试图通过 nil 指针调用一个方法。在这里的 GetName 方法的实现中,如果接收器是 nil,就会引发 panic,因为在方法内部试图访问 a.name,这需要对 nil 指针进行解引用操作。

所以,执行 demo() 函数的结果将是:

anyA 不是 nil
anyA 是 AAA
A 不是 nil
进来了

紧接着的是程序会因为 nil 的解引用崩溃。

对于 demo 函数,它展示了如何检查一个变量是否实现了某个接口,然而,关于接收器为 nil 的方法调用,必须特别小心。在 Go 中,允许 nil 接收器的方法调用,只要方法内部正确处理 nil。但在很多情况下,这可能不是预期的行为,按照正常的思路一般都会认为接收器不会是nil,这就是需要注意的点。

一个更健壮的做法是在设计接口和方法时避免这种状况,例如不返回包含 nil 的接口类型,或者在方法内部检查接收器是否为 nil。这样,调用者就不需要编写复杂的 nil 检查逻辑,代码的安全性和可读性都会提高。


一点点笔记,以便以后翻阅。


http://www.kler.cn/a/413072.html

相关文章:

  • 搭建私有docker仓库
  • CTF之密码学(BF与Ook)
  • CentOS Docker 安装
  • v-for产生 You may have an infinite update loop in a component render function
  • Spring Boot教程之十: 使用 Spring Boot 实现从数据库动态下拉列表
  • goframe开发一个企业网站 在vue-next-admin 显示验证码 19
  • 基于STM32的智能家居电器控制系统
  • 林业产品智能推荐引擎:Spring Boot篇
  • django小项目
  • 【微信小程序】- 位置权限
  • 数据结构C语言描述5(图文结合)--广义表讲解与实现
  • 小程序基础:流程。
  • 计算机网络:运输层 —— TCP 的超时重传机制
  • LLM-pruner源码解析
  • VS2022的MFC的ReadString的问题
  • 熔断限流:业务实现自我保护
  • C++ ADL参数依赖查找
  • scala统计词频
  • 嵌入式工程师面试笔试总结——day2
  • TorchMoji使用教程/环境配置(2024)
  • 记录下在html文件中如何直接使用npm依赖,以threejs为例
  • sentry前端接入 报错403
  • 2022 年 3 月青少年软编等考 C 语言三级真题解析
  • YourPHPCMS Register_checkEmail存在sql注入漏洞
  • uniapp中的事件:v-on
  • Spring Boot 3 集成 Spring Security(3)数据管理